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:
authorYimingWu <xp8110@outlook.com>2019-09-04 06:30:16 +0300
committerYimingWu <xp8110@outlook.com>2019-09-04 06:30:16 +0300
commit55a6fc0be3ffa823052aba45bec12c6902e7bd53 (patch)
treefb8cb4e411e22fcb49e443ea4da636660618877f /source/blender
parentafac2afbfcdb06a2d2655e63d0b8bc35b1aba18e (diff)
parentda25aca2677ec2b566cad1809eebceee22b28b53 (diff)
Merge remote-tracking branch 'origin/master' into soc-2019-npr
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/CMakeLists.txt4
-rw-r--r--source/blender/alembic/ABC_alembic.h6
-rw-r--r--source/blender/alembic/intern/abc_mball.h2
-rw-r--r--source/blender/alembic/intern/abc_mesh.cc32
-rw-r--r--source/blender/alembic/intern/abc_mesh.h10
-rw-r--r--source/blender/alembic/intern/abc_object.cc8
-rw-r--r--source/blender/alembic/intern/abc_object.h2
-rw-r--r--source/blender/alembic/intern/abc_util.h1
-rw-r--r--source/blender/alembic/intern/alembic_capi.cc41
-rw-r--r--source/blender/blendthumb/CMakeLists.txt38
-rw-r--r--source/blender/blendthumb/src/BlendThumb.def5
-rw-r--r--source/blender/blendthumb/src/BlendThumb.rc26
-rw-r--r--source/blender/blendthumb/src/BlenderThumb.cpp313
-rw-r--r--source/blender/blendthumb/src/Dll.cpp280
-rw-r--r--source/blender/blenfont/intern/blf_thumbs.c2
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h83
-rw-r--r--source/blender/blenkernel/BKE_anim.h1
-rw-r--r--source/blender/blenkernel/BKE_animsys.h1
-rw-r--r--source/blender/blenkernel/BKE_armature.h5
-rw-r--r--source/blender/blenkernel/BKE_blender_undo.h1
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h4
-rw-r--r--source/blender/blenkernel/BKE_brush.h2
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h63
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h1
-rw-r--r--source/blender/blenkernel/BKE_camera.h2
-rw-r--r--source/blender/blenkernel/BKE_cdderivedmesh.h76
-rw-r--r--source/blender/blenkernel/BKE_cloth.h1
-rw-r--r--source/blender/blenkernel/BKE_collection.h8
-rw-r--r--source/blender/blenkernel/BKE_collision.h2
-rw-r--r--source/blender/blenkernel/BKE_context.h8
-rw-r--r--source/blender/blenkernel/BKE_curve.h22
-rw-r--r--source/blender/blenkernel/BKE_displist.h2
-rw-r--r--source/blender/blenkernel/BKE_dynamicpaint.h2
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h9
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h3
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h36
-rw-r--r--source/blender/blenkernel/BKE_gpencil_modifier.h7
-rw-r--r--source/blender/blenkernel/BKE_image_save.h1
-rw-r--r--source/blender/blenkernel/BKE_key.h11
-rw-r--r--source/blender/blenkernel/BKE_lattice.h14
-rw-r--r--source/blender/blenkernel/BKE_layer.h5
-rw-r--r--source/blender/blenkernel/BKE_library.h8
-rw-r--r--source/blender/blenkernel/BKE_library_override.h4
-rw-r--r--source/blender/blenkernel/BKE_library_remap.h4
-rw-r--r--source/blender/blenkernel/BKE_light.h1
-rw-r--r--source/blender/blenkernel/BKE_linestyle.h1
-rw-r--r--source/blender/blenkernel/BKE_main.h1
-rw-r--r--source/blender/blenkernel/BKE_mask.h1
-rw-r--r--source/blender/blenkernel/BKE_material.h9
-rw-r--r--source/blender/blenkernel/BKE_mball.h2
-rw-r--r--source/blender/blenkernel/BKE_mball_tessellate.h1
-rw-r--r--source/blender/blenkernel/BKE_mesh.h54
-rw-r--r--source/blender/blenkernel/BKE_mesh_iterators.h6
-rw-r--r--source/blender/blenkernel/BKE_mesh_runtime.h1
-rw-r--r--source/blender/blenkernel/BKE_mesh_tangent.h2
-rw-r--r--source/blender/blenkernel/BKE_modifier.h1
-rw-r--r--source/blender/blenkernel/BKE_node.h7
-rw-r--r--source/blender/blenkernel/BKE_object.h1
-rw-r--r--source/blender/blenkernel/BKE_paint.h9
-rw-r--r--source/blender/blenkernel/BKE_particle.h1
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h13
-rw-r--r--source/blender/blenkernel/BKE_scene.h2
-rw-r--r--source/blender/blenkernel/BKE_screen.h2
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h2
-rw-r--r--source/blender/blenkernel/BKE_shader_fx.h11
-rw-r--r--source/blender/blenkernel/BKE_shrinkwrap.h1
-rw-r--r--source/blender/blenkernel/BKE_studiolight.h12
-rw-r--r--source/blender/blenkernel/BKE_subdiv.h2
-rw-r--r--source/blender/blenkernel/BKE_texture.h4
-rw-r--r--source/blender/blenkernel/BKE_tracking.h1
-rw-r--r--source/blender/blenkernel/BKE_workspace.h3
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c269
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c30
-rw-r--r--source/blender/blenkernel/intern/armature.c94
-rw-r--r--source/blender/blenkernel/intern/armature_update.c12
-rw-r--r--source/blender/blenkernel/intern/brush.c1
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c692
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c872
-rw-r--r--source/blender/blenkernel/intern/collection.c35
-rw-r--r--source/blender/blenkernel/intern/constraint.c75
-rw-r--r--source/blender/blenkernel/intern/context.c2
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c6
-rw-r--r--source/blender/blenkernel/intern/curve.c99
-rw-r--r--source/blender/blenkernel/intern/customdata.c30
-rw-r--r--source/blender/blenkernel/intern/displist.c42
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c6
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c8
-rw-r--r--source/blender/blenkernel/intern/editmesh.c23
-rw-r--r--source/blender/blenkernel/intern/editmesh_bvh.c2
-rw-r--r--source/blender/blenkernel/intern/fcurve.c98
-rw-r--r--source/blender/blenkernel/intern/gpencil.c574
-rw-r--r--source/blender/blenkernel/intern/gpencil_modifier.c79
-rw-r--r--source/blender/blenkernel/intern/key.c8
-rw-r--r--source/blender/blenkernel/intern/lattice.c134
-rw-r--r--source/blender/blenkernel/intern/layer.c38
-rw-r--r--source/blender/blenkernel/intern/library.c30
-rw-r--r--source/blender/blenkernel/intern/library_override.c80
-rw-r--r--source/blender/blenkernel/intern/library_remap.c9
-rw-r--r--source/blender/blenkernel/intern/light.c9
-rw-r--r--source/blender/blenkernel/intern/linestyle.c9
-rw-r--r--source/blender/blenkernel/intern/mask.c4
-rw-r--r--source/blender/blenkernel/intern/material.c60
-rw-r--r--source/blender/blenkernel/intern/mball.c7
-rw-r--r--source/blender/blenkernel/intern/mesh.c212
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.c8
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c78
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_merge.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c20
-rw-r--r--source/blender/blenkernel/intern/multires_reshape.c4
-rw-r--r--source/blender/blenkernel/intern/node.c41
-rw-r--r--source/blender/blenkernel/intern/object.c13
-rw-r--r--source/blender/blenkernel/intern/object_update.c2
-rw-r--r--source/blender/blenkernel/intern/ocean.c2
-rw-r--r--source/blender/blenkernel/intern/paint.c12
-rw-r--r--source/blender/blenkernel/intern/particle.c2
-rw-r--r--source/blender/blenkernel/intern/particle_system.c4
-rw-r--r--source/blender/blenkernel/intern/pbvh.c58
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c21
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h5
-rw-r--r--source/blender/blenkernel/intern/pointcache.c59
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c19
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c6
-rw-r--r--source/blender/blenkernel/intern/softbody.c2
-rw-r--r--source/blender/blenkernel/intern/studiolight.c300
-rw-r--r--source/blender/blenkernel/intern/subdiv_mesh.c9
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c403
-rw-r--r--source/blender/blenkernel/intern/texture.c10
-rw-r--r--source/blender/blenkernel/intern/tracking_solver.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_stabilize.c4
-rw-r--r--source/blender/blenkernel/intern/undo_system.c2
-rw-r--r--source/blender/blenkernel/intern/unit.c14
-rw-r--r--source/blender/blenkernel/intern/world.c10
-rw-r--r--source/blender/blenkernel/nla_private.h2
-rw-r--r--source/blender/blenlib/BLI_array.h4
-rw-r--r--source/blender/blenlib/BLI_dynstr.h1
-rw-r--r--source/blender/blenlib/BLI_fileops.h9
-rw-r--r--source/blender/blenlib/BLI_kdopbvh.h6
-rw-r--r--source/blender/blenlib/BLI_listbase.h9
-rw-r--r--source/blender/blenlib/BLI_math_base.h3
-rw-r--r--source/blender/blenlib/BLI_math_geom.h11
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h11
-rw-r--r--source/blender/blenlib/BLI_math_rotation.h2
-rw-r--r--source/blender/blenlib/BLI_math_vector.h11
-rw-r--r--source/blender/blenlib/BLI_memiter.h1
-rw-r--r--source/blender/blenlib/BLI_path_util.h2
-rw-r--r--source/blender/blenlib/BLI_polyfill_2d_beautify.h5
-rw-r--r--source/blender/blenlib/BLI_string.h2
-rw-r--r--source/blender/blenlib/BLI_system.h9
-rw-r--r--source/blender/blenlib/intern/BLI_filelist.c74
-rw-r--r--source/blender/blenlib/intern/BLI_ghash.c4
-rw-r--r--source/blender/blenlib/intern/BLI_kdopbvh.c89
-rw-r--r--source/blender/blenlib/intern/boxpack_2d.c4
-rw-r--r--source/blender/blenlib/intern/delaunay_2d.c93
-rw-r--r--source/blender/blenlib/intern/freetypefont.c2
-rw-r--r--source/blender/blenlib/intern/math_base_inline.c9
-rw-r--r--source/blender/blenlib/intern/math_color.c2
-rw-r--r--source/blender/blenlib/intern/math_geom.c70
-rw-r--r--source/blender/blenlib/intern/math_matrix.c124
-rw-r--r--source/blender/blenlib/intern/math_rotation.c61
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c68
-rw-r--r--source/blender/blenlib/intern/polyfill_2d_beautify.c34
-rw-r--r--source/blender/blenlib/intern/string.c18
-rw-r--r--source/blender/blenlib/intern/system.c13
-rw-r--r--source/blender/blenlib/intern/winstuff.c12
-rw-r--r--source/blender/blenloader/BLO_blend_defs.h2
-rw-r--r--source/blender/blenloader/BLO_readfile.h1
-rw-r--r--source/blender/blenloader/intern/readfile.c53
-rw-r--r--source/blender/blenloader/intern/versioning_250.c11
-rw-r--r--source/blender/blenloader/intern/versioning_270.c2
-rw-r--r--source/blender/blenloader/intern/versioning_280.c175
-rw-r--r--source/blender/blenloader/intern/versioning_cycles.c404
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c8
-rw-r--r--source/blender/blenloader/intern/versioning_userdef.c6
-rw-r--r--source/blender/blenloader/intern/writefile.c9
-rw-r--r--source/blender/blentranslation/msgfmt/msgfmt.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c6
-rw-r--r--source/blender/bmesh/intern/bmesh_mesh_conv.c2
-rw-r--r--source/blender/bmesh/intern/bmesh_opdefines.c23
-rw-r--r--source/blender/bmesh/intern/bmesh_operators_private.h1
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c4
-rw-r--r--source/blender/bmesh/intern/bmesh_query.c30
-rw-r--r--source/blender/bmesh/intern/bmesh_query.h7
-rw-r--r--source/blender/bmesh/intern/bmesh_walkers_impl.c2
-rw-r--r--source/blender/bmesh/operators/bmo_inset.c2
-rw-r--r--source/blender/bmesh/operators/bmo_removedoubles.c31
-rw-r--r--source/blender/bmesh/tools/bmesh_beautify.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c1
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_collapse.c6
-rw-r--r--source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c2
-rw-r--r--source/blender/bmesh/tools/bmesh_region_match.c2
-rw-r--r--source/blender/collada/AnimationExporter.h2
-rw-r--r--source/blender/collada/AnimationImporter.cpp2
-rw-r--r--source/blender/collada/CMakeLists.txt3
-rw-r--r--source/blender/collada/ControllerExporter.h1
-rw-r--r--source/blender/collada/GeometryExporter.h4
-rw-r--r--source/blender/collada/collada.h3
-rw-r--r--source/blender/collada/collada_utils.h2
-rw-r--r--source/blender/compositor/CMakeLists.txt4
-rw-r--r--source/blender/compositor/intern/COM_CompositorContext.h2
-rw-r--r--source/blender/compositor/intern/COM_MemoryBuffer.h2
-rw-r--r--source/blender/compositor/intern/COM_NodeOperation.h2
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.cpp2
-rw-r--r--source/blender/compositor/intern/COM_OpenCLDevice.h4
-rw-r--r--source/blender/compositor/nodes/COM_ImageNode.cpp2
-rw-r--r--source/blender/compositor/nodes/COM_MathNode.cpp36
-rw-r--r--source/blender/compositor/nodes/COM_MixNode.cpp2
-rw-r--r--source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_CompositorOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_DenoiseOperation.cpp112
-rw-r--r--source/blender/compositor/operations/COM_DenoiseOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_GlareGhostOperation.cpp12
-rw-r--r--source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp4
-rw-r--r--source/blender/compositor/operations/COM_GlareStreaksOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_MaskOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_MixOperation.cpp7
-rw-r--r--source/blender/compositor/operations/COM_MixOperation.h4
-rw-r--r--source/blender/compositor/operations/COM_ViewerOperation.cpp2
-rw-r--r--source/blender/compositor/operations/COM_WriteBufferOperation.cpp6
-rw-r--r--source/blender/depsgraph/DEG_depsgraph.h5
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_build.h3
-rw-r--r--source/blender/depsgraph/DEG_depsgraph_query.h5
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cache.cc4
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_cycle.cc2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_map.h1
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_nodes.h6
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc48
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.h3
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_rna.cc14
-rw-r--r--source/blender/depsgraph/intern/depsgraph.h2
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query.cc8
-rw-r--r--source/blender/depsgraph/intern/depsgraph_tag.cc11
-rw-r--r--source/blender/depsgraph/intern/node/deg_node.h1
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_id.h2
-rw-r--r--source/blender/depsgraph/intern/node/deg_node_operation.h1
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/DRW_engine.h12
-rw-r--r--source/blender/draw/DRW_select_buffer.h7
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c18
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.h1
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_lut.c2
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h1
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c14
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c4
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_draw_utils.c76
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c8
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h69
-rw-r--r--source/blender/draw/engines/select/select_draw_utils.c69
-rw-r--r--source/blender/draw/engines/select/select_engine.c80
-rw-r--r--source/blender/draw/engines/select/select_engine.h7
-rw-r--r--source/blender/draw/engines/select/select_private.h1
-rw-r--r--source/blender/draw/engines/select/shaders/selection_id_frag.glsl5
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl14
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_forward_transparent_accum_frag.glsl12
-rw-r--r--source/blender/draw/engines/workbench/workbench_deferred.c14
-rw-r--r--source/blender/draw/engines/workbench/workbench_forward.c24
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c12
-rw-r--r--source/blender/draw/engines/workbench/workbench_private.h17
-rw-r--r--source/blender/draw/intern/DRW_render.h4
-rw-r--r--source/blender/draw/intern/draw_cache.c2
-rw-r--r--source/blender/draw/intern/draw_cache.h2
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.c848
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h4
-rw-r--r--source/blender/draw/intern/draw_cache_impl_displist.c2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c25
-rw-r--r--source/blender/draw/intern/draw_common.c33
-rw-r--r--source/blender/draw/intern/draw_common.h6
-rw-r--r--source/blender/draw/intern/draw_hair.c2
-rw-r--r--source/blender/draw/intern/draw_instance_data.c2
-rw-r--r--source/blender/draw/intern/draw_instance_data.h2
-rw-r--r--source/blender/draw/intern/draw_manager.c55
-rw-r--r--source/blender/draw/intern/draw_manager.h3
-rw-r--r--source/blender/draw/intern/draw_manager_data.c8
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c8
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c2
-rw-r--r--source/blender/draw/intern/draw_select_buffer.c7
-rw-r--r--source/blender/draw/modes/object_mode.c64
-rw-r--r--source/blender/draw/modes/shaders/common_globals_lib.glsl5
-rw-r--r--source/blender/draw/modes/shaders/object_color_axes_vert.glsl35
-rw-r--r--source/blender/draw/modes/shaders/object_empty_image_frag.glsl6
-rw-r--r--source/blender/draw/modes/shaders/object_grid_frag.glsl75
-rw-r--r--source/blender/draw/modes/shaders/object_grid_vert.glsl6
-rw-r--r--source/blender/editors/animation/anim_channels_defines.c2
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c1
-rw-r--r--source/blender/editors/animation/anim_filter.c5
-rw-r--r--source/blender/editors/animation/anim_ipo_utils.c2
-rw-r--r--source/blender/editors/animation/anim_markers.c2
-rw-r--r--source/blender/editors/animation/anim_motion_paths.c5
-rw-r--r--source/blender/editors/animation/drivers.c50
-rw-r--r--source/blender/editors/animation/fmodifier_ui.c4
-rw-r--r--source/blender/editors/animation/keyframes_draw.c4
-rw-r--r--source/blender/editors/animation/keyframing.c36
-rw-r--r--source/blender/editors/animation/keyingsets.c18
-rw-r--r--source/blender/editors/armature/armature_add.c2
-rw-r--r--source/blender/editors/armature/armature_edit.c34
-rw-r--r--source/blender/editors/armature/armature_intern.h1
-rw-r--r--source/blender/editors/armature/armature_select.c16
-rw-r--r--source/blender/editors/armature/armature_utils.c47
-rw-r--r--source/blender/editors/armature/pose_select.c17
-rw-r--r--source/blender/editors/armature/pose_slide.c2
-rw-r--r--source/blender/editors/curve/editcurve.c8
-rw-r--r--source/blender/editors/curve/editcurve_paint.c4
-rw-r--r--source/blender/editors/curve/editcurve_select.c2
-rw-r--r--source/blender/editors/curve/editfont.c214
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c4
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c1
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c11
-rw-r--r--source/blender/editors/gpencil/gpencil_add_monkey.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_add_stroke.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_brush.c159
-rw-r--r--source/blender/editors/gpencil/gpencil_data.c49
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c177
-rw-r--r--source/blender/editors/gpencil/gpencil_fill.c31
-rw-r--r--source/blender/editors/gpencil/gpencil_intern.h23
-rw-r--r--source/blender/editors/gpencil/gpencil_merge.c2
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c35
-rw-r--r--source/blender/editors/gpencil/gpencil_primitive.c12
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c86
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c23
-rw-r--r--source/blender/editors/include/BIF_glutil.h1
-rw-r--r--source/blender/editors/include/ED_armature.h17
-rw-r--r--source/blender/editors/include/ED_clip.h1
-rw-r--r--source/blender/editors/include/ED_fileselect.h47
-rw-r--r--source/blender/editors/include/ED_gizmo_library.h2
-rw-r--r--source/blender/editors/include/ED_gpencil.h5
-rw-r--r--source/blender/editors/include/ED_image.h1
-rw-r--r--source/blender/editors/include/ED_keyframes_draw.h1
-rw-r--r--source/blender/editors/include/ED_keyframing.h2
-rw-r--r--source/blender/editors/include/ED_markers.h1
-rw-r--r--source/blender/editors/include/ED_mesh.h47
-rw-r--r--source/blender/editors/include/ED_object.h10
-rw-r--r--source/blender/editors/include/ED_outliner.h14
-rw-r--r--source/blender/editors/include/ED_screen.h3
-rw-r--r--source/blender/editors/include/ED_sculpt.h3
-rw-r--r--source/blender/editors/include/ED_time_scrub_ui.h1
-rw-r--r--source/blender/editors/include/ED_transform.h24
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h4
-rw-r--r--source/blender/editors/include/ED_uvedit.h1
-rw-r--r--source/blender/editors/include/ED_view3d.h7
-rw-r--r--source/blender/editors/include/UI_icons.h10
-rw-r--r--source/blender/editors/include/UI_interface.h3
-rw-r--r--source/blender/editors/include/UI_resources.h1
-rw-r--r--source/blender/editors/interface/interface.c24
-rw-r--r--source/blender/editors/interface/interface_anim.c4
-rw-r--r--source/blender/editors/interface/interface_context_menu.c42
-rw-r--r--source/blender/editors/interface/interface_draw.c2
-rw-r--r--source/blender/editors/interface/interface_eyedropper_datablock.c53
-rw-r--r--source/blender/editors/interface/interface_eyedropper_driver.c6
-rw-r--r--source/blender/editors/interface/interface_handlers.c30
-rw-r--r--source/blender/editors/interface/interface_icons.c11
-rw-r--r--source/blender/editors/interface/interface_layout.c10
-rw-r--r--source/blender/editors/interface/interface_ops.c124
-rw-r--r--source/blender/editors/interface/interface_region_popup.c8
-rw-r--r--source/blender/editors/interface/interface_region_tooltip.c10
-rw-r--r--source/blender/editors/interface/interface_templates.c83
-rw-r--r--source/blender/editors/interface/interface_utils.c4
-rw-r--r--source/blender/editors/interface/interface_widgets.c70
-rw-r--r--source/blender/editors/interface/resources.c4
-rw-r--r--source/blender/editors/interface/view2d_ops.c2
-rw-r--r--source/blender/editors/mask/mask_shapekey.c2
-rw-r--r--source/blender/editors/mesh/CMakeLists.txt1
-rw-r--r--source/blender/editors/mesh/editmesh_automerge.c517
-rw-r--r--source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c13
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c4
-rw-r--r--source/blender/editors/mesh/editmesh_polybuild.c189
-rw-r--r--source/blender/editors/mesh/editmesh_preselect_elem.c206
-rw-r--r--source/blender/editors/mesh/editmesh_select.c191
-rw-r--r--source/blender/editors/mesh/editmesh_tools.c14
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c20
-rw-r--r--source/blender/editors/mesh/mesh_data.c126
-rw-r--r--source/blender/editors/mesh/mesh_intern.h2
-rw-r--r--source/blender/editors/mesh/mesh_ops.c21
-rw-r--r--source/blender/editors/object/CMakeLists.txt1
-rw-r--r--source/blender/editors/object/object_add.c24
-rw-r--r--source/blender/editors/object/object_constraint.c22
-rw-r--r--source/blender/editors/object/object_data_transform.c333
-rw-r--r--source/blender/editors/object/object_edit.c43
-rw-r--r--source/blender/editors/object/object_gpencil_modifier.c4
-rw-r--r--source/blender/editors/object/object_hook.c4
-rw-r--r--source/blender/editors/object/object_modifier.c12
-rw-r--r--source/blender/editors/object/object_relations.c22
-rw-r--r--source/blender/editors/object/object_remesh.c4
-rw-r--r--source/blender/editors/object/object_select.c19
-rw-r--r--source/blender/editors/object/object_shader_fx.c4
-rw-r--r--source/blender/editors/object/object_transform.c61
-rw-r--r--source/blender/editors/object/object_vgroup.c2
-rw-r--r--source/blender/editors/physics/particle_object.c11
-rw-r--r--source/blender/editors/physics/physics_intern.h1
-rw-r--r--source/blender/editors/physics/physics_pointcache.c12
-rw-r--r--source/blender/editors/render/render_intern.h1
-rw-r--r--source/blender/editors/render/render_shading.c8
-rw-r--r--source/blender/editors/render/render_view.c4
-rw-r--r--source/blender/editors/screen/area.c39
-rw-r--r--source/blender/editors/screen/screen_context.c2
-rw-r--r--source/blender/editors/screen/screen_edit.c98
-rw-r--r--source/blender/editors/screen/screen_ops.c331
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c229
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c4
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h1
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c118
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c223
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h18
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_undo.c2
-rw-r--r--source/blender/editors/sound/sound_ops.c2
-rw-r--r--source/blender/editors/space_action/action_data.c2
-rw-r--r--source/blender/editors/space_action/action_draw.c352
-rw-r--r--source/blender/editors/space_action/action_intern.h2
-rw-r--r--source/blender/editors/space_action/action_select.c10
-rw-r--r--source/blender/editors/space_action/space_action.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_context.c12
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c2
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c4
-rw-r--r--source/blender/editors/space_clip/clip_dopesheet_draw.c3
-rw-r--r--source/blender/editors/space_console/space_console.c3
-rw-r--r--source/blender/editors/space_file/file_draw.c637
-rw-r--r--source/blender/editors/space_file/file_intern.h16
-rw-r--r--source/blender/editors/space_file/file_ops.c144
-rw-r--r--source/blender/editors/space_file/file_panels.c1
-rw-r--r--source/blender/editors/space_file/filelist.c166
-rw-r--r--source/blender/editors/space_file/filelist.h6
-rw-r--r--source/blender/editors/space_file/filesel.c274
-rw-r--r--source/blender/editors/space_file/space_file.c118
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c9
-rw-r--r--source/blender/editors/space_graph/graph_draw.c6
-rw-r--r--source/blender/editors/space_graph/graph_edit.c2
-rw-r--r--source/blender/editors/space_graph/graph_intern.h1
-rw-r--r--source/blender/editors/space_graph/space_graph.c2
-rw-r--r--source/blender/editors/space_image/image_buttons.c2
-rw-r--r--source/blender/editors/space_image/image_intern.h1
-rw-r--r--source/blender/editors/space_image/image_ops.c3
-rw-r--r--source/blender/editors/space_image/space_image.c2
-rw-r--r--source/blender/editors/space_info/info_stats.c2
-rw-r--r--source/blender/editors/space_info/textview.c2
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c6
-rw-r--r--source/blender/editors/space_nla/nla_channels.c6
-rw-r--r--source/blender/editors/space_nla/nla_draw.c4
-rw-r--r--source/blender/editors/space_nla/space_nla.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c46
-rw-r--r--source/blender/editors/space_node/node_draw.c143
-rw-r--r--source/blender/editors/space_node/node_edit.c10
-rw-r--r--source/blender/editors/space_node/node_select.c16
-rw-r--r--source/blender/editors/space_node/node_templates.c2
-rw-r--r--source/blender/editors/space_outliner/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c8
-rw-r--r--source/blender/editors/space_outliner/outliner_dragdrop.c191
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c262
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c255
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h35
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c1
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c449
-rw-r--r--source/blender/editors/space_outliner/outliner_sync.c575
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c149
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c25
-rw-r--r--source/blender/editors/space_outliner/outliner_utils.c140
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c21
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c5
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c23
-rw-r--r--source/blender/editors/space_sequencer/space_sequencer.c2
-rw-r--r--source/blender/editors/space_text/space_text.c3
-rw-r--r--source/blender/editors/space_text/text_ops.c2
-rw-r--r--source/blender/editors/space_view3d/drawobject.c2
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c4
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c118
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c126
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_ruler.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h7
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c47
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c4
-rw-r--r--source/blender/editors/transform/transform.c4
-rw-r--r--source/blender/editors/transform/transform.h10
-rw-r--r--source/blender/editors/transform/transform_conversions.c592
-rw-r--r--source/blender/editors/transform/transform_generics.c11
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c3
-rw-r--r--source/blender/editors/transform/transform_input.c2
-rw-r--r--source/blender/editors/transform/transform_ops.c26
-rw-r--r--source/blender/editors/transform/transform_snap.c95
-rw-r--r--source/blender/editors/transform/transform_snap_object.c226
-rw-r--r--source/blender/editors/undo/ed_undo.c5
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c58
-rw-r--r--source/blender/editors/uvedit/uvedit_intern.h1
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c2
-rw-r--r--source/blender/editors/uvedit/uvedit_unwrap_ops.c2
-rw-r--r--source/blender/freestyle/FRS_freestyle.h1
-rw-r--r--source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp2
-rw-r--r--source/blender/freestyle/intern/scene_graph/FrsMaterial.h16
-rw-r--r--source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h2
-rw-r--r--source/blender/freestyle/intern/scene_graph/NodeTransform.h6
-rw-r--r--source/blender/freestyle/intern/stroke/Curve.h2
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c22
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h4
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c6
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c4
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c7
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c5
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c12
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c5
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c5
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c5
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c34
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c5
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c5
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c5
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c48
-rw-r--r--source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c7
-rw-r--r--source/blender/gpu/CMakeLists.txt90
-rw-r--r--source/blender/gpu/GPU_batch_presets.h3
-rw-r--r--source/blender/gpu/GPU_draw.h6
-rw-r--r--source/blender/gpu/GPU_material.h5
-rw-r--r--source/blender/gpu/GPU_shader_interface.h7
-rw-r--r--source/blender/gpu/GPU_texture.h1
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c94
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h4
-rw-r--r--source/blender/gpu/intern/gpu_draw.c6
-rw-r--r--source/blender/gpu/intern/gpu_element.c19
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c1
-rw-r--r--source/blender/gpu/intern/gpu_material.c13
-rw-r--r--source/blender/gpu/intern/gpu_material_library.h657
-rw-r--r--source/blender/gpu/intern/gpu_private.h3
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c1
-rw-r--r--source/blender/gpu/intern/gpu_texture.c2
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.c2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl4
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl3615
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl13
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl15
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl6
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_background.glsl11
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_bevel.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_blackbody.glsl13
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_bright_contrast.glsl10
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl27
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_camera.glsl6
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_cell_noise.glsl17
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_color_ramp.glsl28
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl111
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_combine_hsv.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_combine_rgb.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_combine_xyz.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl13
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_displacement.glsl12
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl40
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl10
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl32
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_fresnel.glsl37
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_gamma.glsl14
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_geometry.glsl46
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl23
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl15
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl21
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl217
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_holdout.glsl8
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_hue_sat_val.glsl14
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_invert.glsl5
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_layer_weight.glsl19
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_light_falloff.glsl7
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl31
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_map_range.glsl10
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl7
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_math.glsl130
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl101
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl291
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl74
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_normal.glsl5
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_normal_map.glsl22
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl16
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl8
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_output_world.glsl11
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_particle_info.glsl23
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl439
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl16
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl73
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_rgb_to_bw.glsl5
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_separate_hsv.glsl9
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_separate_rgb.glsl6
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_separate_xyz.glsl6
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_set.glsl44
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl25
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_squeeze.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl42
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tangent.glsl25
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl78
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl17
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl44
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_gradient.glsl47
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl355
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_magic.glsl61
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl208
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl19
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl116
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl42
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_white_noise.glsl21
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl92
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_toon.glsl9
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl9
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_transparent.glsl11
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_uv_map.glsl4
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl8
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_vector_displacement.glsl30
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl100
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_velvet.glsl9
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_volume_absorption.glsl8
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl88
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl67
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_volume_scatter.glsl8
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_wireframe.glsl31
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl25
-rw-r--r--source/blender/ikplugin/intern/itasc_plugin.cpp2
-rw-r--r--source/blender/imbuf/IMB_imbuf.h6
-rw-r--r--source/blender/imbuf/intern/allocimbuf.c4
-rw-r--r--source/blender/imbuf/intern/scaling.c4
-rw-r--r--source/blender/makesdna/DNA_ID.h4
-rw-r--r--source/blender/makesdna/DNA_action_types.h3
-rw-r--r--source/blender/makesdna/DNA_anim_types.h30
-rw-r--r--source/blender/makesdna/DNA_brush_types.h5
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h25
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h3
-rw-r--r--source/blender/makesdna/DNA_documentation.h2
-rw-r--r--source/blender/makesdna/DNA_gpencil_modifier_types.h44
-rw-r--r--source/blender/makesdna/DNA_gpencil_types.h2
-rw-r--r--source/blender/makesdna/DNA_light_types.h1
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h7
-rw-r--r--source/blender/makesdna/DNA_meshdata_types.h6
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h2
-rw-r--r--source/blender/makesdna/DNA_node_types.h80
-rw-r--r--source/blender/makesdna/DNA_object_fluidsim_types.h1
-rw-r--r--source/blender/makesdna/DNA_object_types.h26
-rw-r--r--source/blender/makesdna/DNA_outliner_types.h4
-rw-r--r--source/blender/makesdna/DNA_scene_types.h40
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h2
-rw-r--r--source/blender/makesdna/DNA_space_types.h57
-rw-r--r--source/blender/makesdna/DNA_texture_types.h1
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h3
-rw-r--r--source/blender/makesdna/DNA_view3d_types.h5
-rw-r--r--source/blender/makesdna/DNA_windowmanager_types.h18
-rw-r--r--source/blender/makesdna/DNA_world_types.h1
-rw-r--r--source/blender/makesdna/intern/dna_genfile.c4
-rw-r--r--source/blender/makesrna/RNA_access.h35
-rw-r--r--source/blender/makesrna/RNA_enum_types.h1
-rw-r--r--source/blender/makesrna/RNA_types.h8
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt2
-rw-r--r--source/blender/makesrna/intern/makesrna.c8
-rw-r--r--source/blender/makesrna/intern/rna_ID.c40
-rw-r--r--source/blender/makesrna/intern/rna_access.c1203
-rw-r--r--source/blender/makesrna/intern/rna_access_compare_override.c1099
-rw-r--r--source/blender/makesrna/intern/rna_access_internal.h34
-rw-r--r--source/blender/makesrna/intern/rna_action.c8
-rw-r--r--source/blender/makesrna/intern/rna_animation.c10
-rw-r--r--source/blender/makesrna/intern/rna_armature.c116
-rw-r--r--source/blender/makesrna/intern/rna_boid.c12
-rw-r--r--source/blender/makesrna/intern/rna_brush.c40
-rw-r--r--source/blender/makesrna/intern/rna_camera.c23
-rw-r--r--source/blender/makesrna/intern/rna_cloth.c13
-rw-r--r--source/blender/makesrna/intern/rna_collection.c11
-rw-r--r--source/blender/makesrna/intern/rna_color.c26
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c73
-rw-r--r--source/blender/makesrna/intern/rna_context.c4
-rw-r--r--source/blender/makesrna/intern/rna_curve.c55
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c2
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c56
-rw-r--r--source/blender/makesrna/intern/rna_fluidsim.c8
-rw-r--r--source/blender/makesrna/intern/rna_gpencil.c54
-rw-r--r--source/blender/makesrna/intern/rna_gpencil_modifier.c152
-rw-r--r--source/blender/makesrna/intern/rna_image.c38
-rw-r--r--source/blender/makesrna/intern/rna_internal.h5
-rw-r--r--source/blender/makesrna/intern/rna_internal_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_key.c27
-rw-r--r--source/blender/makesrna/intern/rna_lattice.c16
-rw-r--r--source/blender/makesrna/intern/rna_layer.c6
-rw-r--r--source/blender/makesrna/intern/rna_light.c4
-rw-r--r--source/blender/makesrna/intern/rna_lightprobe.c3
-rw-r--r--source/blender/makesrna/intern/rna_linestyle.c16
-rw-r--r--source/blender/makesrna/intern/rna_mask.c22
-rw-r--r--source/blender/makesrna/intern/rna_material.c23
-rw-r--r--source/blender/makesrna/intern/rna_mesh.c28
-rw-r--r--source/blender/makesrna/intern/rna_mesh_api.c5
-rw-r--r--source/blender/makesrna/intern/rna_meta.c6
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c108
-rw-r--r--source/blender/makesrna/intern/rna_movieclip.c10
-rw-r--r--source/blender/makesrna/intern/rna_nla.c22
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c201
-rw-r--r--source/blender/makesrna/intern/rna_object.c213
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c6
-rw-r--r--source/blender/makesrna/intern/rna_object_force.c195
-rw-r--r--source/blender/makesrna/intern/rna_particle.c63
-rw-r--r--source/blender/makesrna/intern/rna_pose.c47
-rw-r--r--source/blender/makesrna/intern/rna_rigidbody.c8
-rw-r--r--source/blender/makesrna/intern/rna_rna.c146
-rw-r--r--source/blender/makesrna/intern/rna_scene.c209
-rw-r--r--source/blender/makesrna/intern/rna_screen.c2
-rw-r--r--source/blender/makesrna/intern/rna_sculpt_paint.c15
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c76
-rw-r--r--source/blender/makesrna/intern/rna_shader_fx.c29
-rw-r--r--source/blender/makesrna/intern/rna_smoke.c6
-rw-r--r--source/blender/makesrna/intern/rna_space.c137
-rw-r--r--source/blender/makesrna/intern/rna_speaker.c1
-rw-r--r--source/blender/makesrna/intern/rna_texture.c24
-rw-r--r--source/blender/makesrna/intern/rna_timeline.c1
-rw-r--r--source/blender/makesrna/intern/rna_tracking.c76
-rw-r--r--source/blender/makesrna/intern/rna_ui.c2
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c27
-rw-r--r--source/blender/makesrna/intern/rna_vfont.c4
-rw-r--r--source/blender/makesrna/intern/rna_wm.c10
-rw-r--r--source/blender/makesrna/intern/rna_wm_gizmo.c2
-rw-r--r--source/blender/makesrna/intern/rna_workspace.c2
-rw-r--r--source/blender/makesrna/intern/rna_world.c10
-rw-r--r--source/blender/modifiers/CMakeLists.txt4
-rw-r--r--source/blender/modifiers/intern/MOD_armature.c2
-rw-r--r--source/blender/modifiers/intern/MOD_array.c42
-rw-r--r--source/blender/modifiers/intern/MOD_boolean.c7
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c2
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c2
-rw-r--r--source/blender/modifiers/intern/MOD_correctivesmooth.c6
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c7
-rw-r--r--source/blender/modifiers/intern/MOD_datatransfer.c9
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim_util.c2
-rw-r--r--source/blender/modifiers/intern/MOD_fluidsim_util.h2
-rw-r--r--source/blender/modifiers/intern/MOD_lattice.c7
-rw-r--r--source/blender/modifiers/intern/MOD_mask.c22
-rw-r--r--source/blender/modifiers/intern/MOD_meshdeform.c9
-rw-r--r--source/blender/modifiers/intern/MOD_meshsequencecache.c10
-rw-r--r--source/blender/modifiers/intern/MOD_multires.c4
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c7
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c2
-rw-r--r--source/blender/modifiers/intern/MOD_remesh.c4
-rw-r--r--source/blender/modifiers/intern/MOD_shrinkwrap.c14
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c4
-rw-r--r--source/blender/modifiers/intern/MOD_surface.c2
-rw-r--r--source/blender/modifiers/intern/MOD_surfacedeform.c8
-rw-r--r--source/blender/modifiers/intern/MOD_util.c2
-rw-r--r--source/blender/modifiers/intern/MOD_util.h2
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c2
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgproximity.c4
-rw-r--r--source/blender/nodes/CMakeLists.txt4
-rw-r--r--source/blender/nodes/NOD_shader.h2
-rw-r--r--source/blender/nodes/NOD_static_types.h4
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_denoise.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_outputFile.c2
-rw-r--r--source/blender/nodes/composite/nodes/node_composite_switchview.c2
-rw-r--r--source/blender/nodes/intern/node_socket.c2
-rw-r--r--source/blender/nodes/intern/node_util.c2
-rw-r--r--source/blender/nodes/intern/node_util.h2
-rw-r--r--source/blender/nodes/shader/node_shader_tree.c10
-rw-r--r--source/blender/nodes/shader/node_shader_util.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mapping.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_math.c368
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_mixRgb.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_normal_map.c8
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_object_info.c18
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c6
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c10
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c76
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectMath.c155
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vectTransform.c2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_vector_math.c113
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_volume_info.c56
-rw-r--r--source/blender/nodes/texture/nodes/node_texture_math.c36
-rw-r--r--source/blender/physics/BPH_mass_spring.h1
-rw-r--r--source/blender/physics/intern/BPH_mass_spring.cpp2
-rw-r--r--source/blender/physics/intern/implicit.h2
-rw-r--r--source/blender/python/bmesh/bmesh_py_types_meshdata.c8
-rw-r--r--source/blender/python/intern/CMakeLists.txt4
-rw-r--r--source/blender/python/intern/bpy_app_build_options.c7
-rw-r--r--source/blender/python/intern/bpy_app_translations.c2
-rw-r--r--source/blender/python/intern/bpy_interface.c4
-rw-r--r--source/blender/python/intern/bpy_msgbus.c4
-rw-r--r--source/blender/python/intern/bpy_operator_wrap.c2
-rw-r--r--source/blender/python/intern/bpy_rna.c88
-rw-r--r--source/blender/python/intern/bpy_rna_anim.c14
-rw-r--r--source/blender/python/intern/bpy_rna_driver.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Quaternion.c2
-rw-r--r--source/blender/python/mathutils/mathutils_Vector.c6
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c6
-rw-r--r--source/blender/render/extern/include/RE_engine.h1
-rw-r--r--source/blender/render/extern/include/RE_pipeline.h5
-rw-r--r--source/blender/render/extern/include/RE_render_ext.h3
-rw-r--r--source/blender/render/extern/include/RE_shader_ext.h2
-rw-r--r--source/blender/render/intern/source/bake_api.c2
-rw-r--r--source/blender/render/intern/source/imagetexture.c2
-rw-r--r--source/blender/render/intern/source/pipeline.c4
-rw-r--r--source/blender/windowmanager/WM_api.h9
-rw-r--r--source/blender/windowmanager/WM_types.h1
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h2
-rw-r--r--source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c4
-rw-r--r--source/blender/windowmanager/gizmo/wm_gizmo_fn.h2
-rw-r--r--source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h2
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c87
-rw-r--r--source/blender/windowmanager/intern/wm_files.c113
-rw-r--r--source/blender/windowmanager/intern/wm_files_link.c4
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c1
-rw-r--r--source/blender/windowmanager/intern/wm_operator_props.c32
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c46
-rw-r--r--source/blender/windowmanager/intern/wm_splash_screen.c20
-rw-r--r--source/blender/windowmanager/intern/wm_window.c26
-rw-r--r--source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c26
-rw-r--r--source/blender/windowmanager/message_bus/wm_message_bus.h7
-rw-r--r--source/blender/windowmanager/wm_window.h4
813 files changed, 21902 insertions, 13536 deletions
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 76442048594..203543b0ef0 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -153,3 +153,7 @@ endif()
if(WITH_ALEMBIC)
add_subdirectory(alembic)
endif()
+
+if(WIN32)
+ add_subdirectory(blendthumb)
+endif()
diff --git a/source/blender/alembic/ABC_alembic.h b/source/blender/alembic/ABC_alembic.h
index 653382017d6..696e0ff1810 100644
--- a/source/blender/alembic/ABC_alembic.h
+++ b/source/blender/alembic/ABC_alembic.h
@@ -117,6 +117,12 @@ struct Mesh *ABC_read_mesh(struct CacheReader *reader,
const char **err_str,
int flags);
+bool ABC_mesh_topology_changed(struct CacheReader *reader,
+ struct Object *ob,
+ struct Mesh *existing_mesh,
+ const float time,
+ const char **err_str);
+
void CacheReader_incref(struct CacheReader *reader);
void CacheReader_free(struct CacheReader *reader);
diff --git a/source/blender/alembic/intern/abc_mball.h b/source/blender/alembic/intern/abc_mball.h
index 770fa6fdf8c..4be977fa8f5 100644
--- a/source/blender/alembic/intern/abc_mball.h
+++ b/source/blender/alembic/intern/abc_mball.h
@@ -24,9 +24,7 @@
#include "abc_object.h"
#include "abc_mesh.h"
-struct EvaluationContext;
struct Main;
-struct MetaBall;
struct Object;
/* AbcMBallWriter converts the metaballs to meshes at every frame,
diff --git a/source/blender/alembic/intern/abc_mesh.cc b/source/blender/alembic/intern/abc_mesh.cc
index 6647ca83bd6..8728303923a 100644
--- a/source/blender/alembic/intern/abc_mesh.cc
+++ b/source/blender/alembic/intern/abc_mesh.cc
@@ -1131,6 +1131,31 @@ bool AbcMeshReader::accepts_object_type(
return true;
}
+bool AbcMeshReader::topology_changed(Mesh *existing_mesh, const ISampleSelector &sample_sel)
+{
+ IPolyMeshSchema::Sample sample;
+ try {
+ sample = m_schema.getValue(sample_sel);
+ }
+ catch (Alembic::Util::Exception &ex) {
+ printf("Alembic: error reading mesh sample for '%s/%s' at time %f: %s\n",
+ m_iobject.getFullName().c_str(),
+ m_schema.getName().c_str(),
+ sample_sel.getRequestedTime(),
+ ex.what());
+ // A similar error in read_mesh() would just return existing_mesh.
+ return false;
+ }
+
+ const P3fArraySamplePtr &positions = sample.getPositions();
+ const Alembic::Abc::Int32ArraySamplePtr &face_indices = sample.getFaceIndices();
+ const Alembic::Abc::Int32ArraySamplePtr &face_counts = sample.getFaceCounts();
+
+ return positions->size() != existing_mesh->totvert ||
+ face_counts->size() != existing_mesh->totpoly ||
+ face_indices->size() != existing_mesh->totloop;
+}
+
Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh,
const ISampleSelector &sample_sel,
int read_flag,
@@ -1162,10 +1187,7 @@ Mesh *AbcMeshReader::read_mesh(Mesh *existing_mesh,
ImportSettings settings;
settings.read_flag |= read_flag;
- bool topology_changed = positions->size() != existing_mesh->totvert ||
- face_counts->size() != existing_mesh->totpoly ||
- face_indices->size() != existing_mesh->totloop;
- if (topology_changed) {
+ if (topology_changed(existing_mesh, sample_sel)) {
new_mesh = BKE_mesh_new_nomain_from_template(
existing_mesh, positions->size(), 0, 0, face_indices->size(), face_counts->size());
@@ -1314,7 +1336,7 @@ static void read_subd_sample(const std::string &iobject_full_name,
if ((settings->read_flag & MOD_MESHSEQ_READ_POLY) != 0) {
/* Alembic's 'SubD' scheme is used to store subdivision surfaces, i.e. the pre-subdivision
- * mesh. Currently we don't add a subdivison modifier when we load such data. This code is
+ * mesh. Currently we don't add a subdivision modifier when we load such data. This code is
* assuming that the subdivided surface should be smooth, and sets a flag that will eventually
* mark all polygons as such. */
abc_mesh_data.poly_flag_smooth = true;
diff --git a/source/blender/alembic/intern/abc_mesh.h b/source/blender/alembic/intern/abc_mesh.h
index 859ab121eb6..c15fb948e03 100644
--- a/source/blender/alembic/intern/abc_mesh.h
+++ b/source/blender/alembic/intern/abc_mesh.h
@@ -100,16 +100,18 @@ class AbcMeshReader : public AbcObjectReader {
public:
AbcMeshReader(const Alembic::Abc::IObject &object, ImportSettings &settings);
- bool valid() const;
+ bool valid() const override;
bool accepts_object_type(const Alembic::AbcCoreAbstract::ObjectHeader &alembic_header,
const Object *const ob,
- const char **err_str) const;
- void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel);
+ const char **err_str) const override;
+ void readObjectData(Main *bmain, const Alembic::Abc::ISampleSelector &sample_sel) override;
struct Mesh *read_mesh(struct Mesh *existing_mesh,
const Alembic::Abc::ISampleSelector &sample_sel,
int read_flag,
- const char **err_str);
+ const char **err_str) override;
+ bool topology_changed(Mesh *existing_mesh,
+ const Alembic::Abc::ISampleSelector &sample_sel) override;
private:
void readFaceSetsSample(Main *bmain,
diff --git a/source/blender/alembic/intern/abc_object.cc b/source/blender/alembic/intern/abc_object.cc
index f863fe4fee7..ebebbc0da1e 100644
--- a/source/blender/alembic/intern/abc_object.cc
+++ b/source/blender/alembic/intern/abc_object.cc
@@ -246,6 +246,14 @@ struct Mesh *AbcObjectReader::read_mesh(struct Mesh *existing_mesh,
return existing_mesh;
}
+bool AbcObjectReader::topology_changed(Mesh * /*existing_mesh*/,
+ const Alembic::Abc::ISampleSelector & /*sample_sel*/)
+{
+ /* The default implementation of read_mesh() just returns the original mesh, so never changes the
+ * topology. */
+ return false;
+}
+
void AbcObjectReader::setupObjectTransform(const float time)
{
bool is_constant = false;
diff --git a/source/blender/alembic/intern/abc_object.h b/source/blender/alembic/intern/abc_object.h
index 537f24ab7d6..efe78b9017c 100644
--- a/source/blender/alembic/intern/abc_object.h
+++ b/source/blender/alembic/intern/abc_object.h
@@ -190,6 +190,8 @@ class AbcObjectReader {
const Alembic::Abc::ISampleSelector &sample_sel,
int read_flag,
const char **err_str);
+ virtual bool topology_changed(Mesh *existing_mesh,
+ const Alembic::Abc::ISampleSelector &sample_sel);
/** Reads the object matrix and sets up an object transform if animated. */
void setupObjectTransform(const float time);
diff --git a/source/blender/alembic/intern/abc_util.h b/source/blender/alembic/intern/abc_util.h
index f7f662212fd..5eb0ed70599 100644
--- a/source/blender/alembic/intern/abc_util.h
+++ b/source/blender/alembic/intern/abc_util.h
@@ -44,7 +44,6 @@ using Alembic::Abc::chrono_t;
class AbcObjectReader;
struct ImportSettings;
-struct Base;
struct ID;
struct Object;
diff --git a/source/blender/alembic/intern/alembic_capi.cc b/source/blender/alembic/intern/alembic_capi.cc
index d63b310fef7..dc525e0c46c 100644
--- a/source/blender/alembic/intern/alembic_capi.cc
+++ b/source/blender/alembic/intern/alembic_capi.cc
@@ -937,12 +937,7 @@ void ABC_get_transform(CacheReader *reader, float r_mat[4][4], float time, float
/* ************************************************************************** */
-Mesh *ABC_read_mesh(CacheReader *reader,
- Object *ob,
- Mesh *existing_mesh,
- const float time,
- const char **err_str,
- int read_flag)
+static AbcObjectReader *get_abc_reader(CacheReader *reader, Object *ob, const char **err_str)
{
AbcObjectReader *abc_reader = reinterpret_cast<AbcObjectReader *>(reader);
IObject iobject = abc_reader->iobject();
@@ -958,12 +953,44 @@ Mesh *ABC_read_mesh(CacheReader *reader,
return NULL;
}
+ return abc_reader;
+}
+
+static ISampleSelector sample_selector_for_time(float time)
+{
/* kFloorIndex is used to be compatible with non-interpolating
* properties; they use the floor. */
- ISampleSelector sample_sel(time, ISampleSelector::kFloorIndex);
+ return ISampleSelector(time, ISampleSelector::kFloorIndex);
+}
+
+Mesh *ABC_read_mesh(CacheReader *reader,
+ Object *ob,
+ Mesh *existing_mesh,
+ const float time,
+ const char **err_str,
+ int read_flag)
+{
+ AbcObjectReader *abc_reader = get_abc_reader(reader, ob, err_str);
+ if (abc_reader == NULL) {
+ return NULL;
+ }
+
+ ISampleSelector sample_sel = sample_selector_for_time(time);
return abc_reader->read_mesh(existing_mesh, sample_sel, read_flag, err_str);
}
+bool ABC_mesh_topology_changed(
+ CacheReader *reader, Object *ob, Mesh *existing_mesh, const float time, const char **err_str)
+{
+ AbcObjectReader *abc_reader = get_abc_reader(reader, ob, err_str);
+ if (abc_reader == NULL) {
+ return false;
+ }
+
+ ISampleSelector sample_sel = sample_selector_for_time(time);
+ return abc_reader->topology_changed(existing_mesh, sample_sel);
+}
+
/* ************************************************************************** */
void CacheReader_free(CacheReader *reader)
diff --git a/source/blender/blendthumb/CMakeLists.txt b/source/blender/blendthumb/CMakeLists.txt
new file mode 100644
index 00000000000..6c786dfcc7a
--- /dev/null
+++ b/source/blender/blendthumb/CMakeLists.txt
@@ -0,0 +1,38 @@
+# ***** BEGIN GPL LICENSE BLOCK *****
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The Original Code is Copyright (C) 2006, Blender Foundation
+# All rights reserved.
+# ***** END GPL LICENSE BLOCK *****
+
+#-----------------------------------------------------------------------------
+include_directories(${ZLIB_INCLUDE_DIRS})
+
+set(SRC
+ src/BlenderThumb.cpp
+ src/BlendThumb.def
+ src/BlendThumb.rc
+ src/Dll.cpp
+)
+
+add_library(BlendThumb SHARED ${SRC})
+target_link_libraries(BlendThumb ${ZLIB_LIBRARIES})
+
+install(
+ FILES $<TARGET_FILE:BlendThumb>
+ COMPONENT Blender
+ DESTINATION "."
+)
diff --git a/source/blender/blendthumb/src/BlendThumb.def b/source/blender/blendthumb/src/BlendThumb.def
new file mode 100644
index 00000000000..71f9236735f
--- /dev/null
+++ b/source/blender/blendthumb/src/BlendThumb.def
@@ -0,0 +1,5 @@
+EXPORTS
+ DllGetClassObject PRIVATE
+ DllCanUnloadNow PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE \ No newline at end of file
diff --git a/source/blender/blendthumb/src/BlendThumb.rc b/source/blender/blendthumb/src/BlendThumb.rc
new file mode 100644
index 00000000000..5dfd416b0c5
--- /dev/null
+++ b/source/blender/blendthumb/src/BlendThumb.rc
@@ -0,0 +1,26 @@
+#define IDR_VERSION1 1
+
+IDR_VERSION1 VERSIONINFO
+FILEVERSION 1,4,0,0
+PRODUCTVERSION 2,78,0,0
+FILEOS 0x00000004
+FILETYPE 0x00000002
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "FFFF04B0"
+ BEGIN
+ VALUE "FileVersion", "1.4\0"
+ VALUE "ProductVersion", "2.78\0"
+ VALUE "FileDescription", "Blender Thumbnail Handler\0"
+ VALUE "OriginalFilename", "BlendThumb.dll\0"
+ VALUE "ProductName", "Blender\0"
+ VALUE "LegalCopyright", "GPL2, 2016\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 0x04B0
+ END
+END
+
diff --git a/source/blender/blendthumb/src/BlenderThumb.cpp b/source/blender/blendthumb/src/BlenderThumb.cpp
new file mode 100644
index 00000000000..94dae437260
--- /dev/null
+++ b/source/blender/blendthumb/src/BlenderThumb.cpp
@@ -0,0 +1,313 @@
+/*
+ * 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.
+ */
+
+#include <shlwapi.h>
+#include <thumbcache.h> // For IThumbnailProvider.
+#include <new>
+
+#pragma comment(lib, "shlwapi.lib")
+
+// this thumbnail provider implements IInitializeWithStream to enable being hosted
+// in an isolated process for robustness
+
+class CBlendThumb : public IInitializeWithStream, public IThumbnailProvider {
+ public:
+ CBlendThumb() : _cRef(1), _pStream(NULL)
+ {
+ }
+
+ virtual ~CBlendThumb()
+ {
+ if (_pStream) {
+ _pStream->Release();
+ }
+ }
+
+ // IUnknown
+ IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
+ {
+ static const QITAB qit[] = {
+ QITABENT(CBlendThumb, IInitializeWithStream),
+ QITABENT(CBlendThumb, IThumbnailProvider),
+ {0},
+ };
+ return QISearch(this, qit, riid, ppv);
+ }
+
+ IFACEMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&_cRef);
+ }
+
+ IFACEMETHODIMP_(ULONG) Release()
+ {
+ ULONG cRef = InterlockedDecrement(&_cRef);
+ if (!cRef) {
+ delete this;
+ }
+ return cRef;
+ }
+
+ // IInitializeWithStream
+ IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode);
+
+ // IThumbnailProvider
+ IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha);
+
+ private:
+ long _cRef;
+ IStream *_pStream; // provided during initialization.
+};
+
+HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv)
+{
+ CBlendThumb *pNew = new (std::nothrow) CBlendThumb();
+ HRESULT hr = pNew ? S_OK : E_OUTOFMEMORY;
+ if (SUCCEEDED(hr)) {
+ hr = pNew->QueryInterface(riid, ppv);
+ pNew->Release();
+ }
+ return hr;
+}
+
+// IInitializeWithStream
+IFACEMETHODIMP CBlendThumb::Initialize(IStream *pStream, DWORD)
+{
+ HRESULT hr = E_UNEXPECTED; // can only be inited once
+ if (_pStream == NULL) {
+ // take a reference to the stream if we have not been inited yet
+ hr = pStream->QueryInterface(&_pStream);
+ }
+ return hr;
+}
+
+#include <math.h>
+#include <zlib.h>
+#include "Wincodec.h"
+const unsigned char gzip_magic[3] = {0x1f, 0x8b, 0x08};
+
+// IThumbnailProvider
+IFACEMETHODIMP CBlendThumb::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha)
+{
+ ULONG BytesRead;
+ HRESULT hr = S_FALSE;
+ LARGE_INTEGER SeekPos;
+
+ // Compressed?
+ unsigned char in_magic[3];
+ _pStream->Read(&in_magic, 3, &BytesRead);
+ bool gzipped = true;
+ for (int i = 0; i < 3; i++)
+ if (in_magic[i] != gzip_magic[i]) {
+ gzipped = false;
+ break;
+ }
+
+ if (gzipped) {
+ // Zlib inflate
+ z_stream stream;
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ // Get compressed file length
+ SeekPos.QuadPart = 0;
+ _pStream->Seek(SeekPos, STREAM_SEEK_END, NULL);
+
+ // Get compressed and uncompressed size
+ uLong source_size;
+ uLongf dest_size;
+ // SeekPos.QuadPart = -4; // last 4 bytes define size of uncompressed file
+ // ULARGE_INTEGER Tell;
+ //_pStream->Seek(SeekPos,STREAM_SEEK_END,&Tell);
+ // source_size = (uLong)Tell.QuadPart + 4; // src
+ //_pStream->Read(&dest_size,4,&BytesRead); // dest
+ dest_size = 1024 * 70; // thumbnail is currently always inside the first 65KB...if it moves or
+ // enlargens this line will have to change or go!
+ source_size = (uLong)max(SeekPos.QuadPart, dest_size); // for safety, assume no compression
+
+ // Input
+ Bytef *src = new Bytef[source_size];
+ stream.next_in = (Bytef *)src;
+ stream.avail_in = (uInt)source_size;
+
+ // Output
+ Bytef *dest = new Bytef[dest_size];
+ stream.next_out = (Bytef *)dest;
+ stream.avail_out = dest_size;
+
+ // IStream to src
+ SeekPos.QuadPart = 0;
+ _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
+ _pStream->Read(src, source_size, &BytesRead);
+
+ // Do the inflation
+ int err;
+ err = inflateInit2(&stream, 16); // 16 means "gzip"...nice!
+ err = inflate(&stream, Z_FINISH);
+ err = inflateEnd(&stream);
+
+ // Replace the IStream, which is read-only
+ _pStream->Release();
+ _pStream = SHCreateMemStream(dest, dest_size);
+
+ delete[] src;
+ delete[] dest;
+ }
+
+ // Blender version, early out if sub 2.5
+ SeekPos.QuadPart = 9;
+ _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
+ char version[4];
+ version[3] = '\0';
+ _pStream->Read(&version, 3, &BytesRead);
+ if (BytesRead != 3)
+ return E_UNEXPECTED;
+ int iVersion = atoi(version);
+ if (iVersion < 250)
+ return S_FALSE;
+
+ // 32 or 64 bit blend?
+ SeekPos.QuadPart = 7;
+ _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
+
+ char _PointerSize;
+ _pStream->Read(&_PointerSize, 1, &BytesRead);
+
+ int PointerSize = _PointerSize == '_' ? 4 : 8;
+ int HeaderSize = 16 + PointerSize;
+
+ // Find and read thumbnail ("TEST") block
+ SeekPos.QuadPart = 12;
+ _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
+ int BlockOffset = 12;
+ while (_pStream) {
+ // Scan current block
+ char BlockName[5];
+ BlockName[4] = '\0';
+ int BlockSize = 0;
+
+ if (_pStream->Read(BlockName, 4, &BytesRead) == S_OK &&
+ _pStream->Read((void *)&BlockSize, 4, &BytesRead) == S_OK) {
+ if (strcmp(BlockName, "TEST") != 0) {
+ SeekPos.QuadPart = BlockOffset += HeaderSize + BlockSize;
+ _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
+ continue;
+ }
+ }
+ else
+ break; // eof
+
+ // Found the block
+ SeekPos.QuadPart = BlockOffset + HeaderSize;
+ _pStream->Seek(SeekPos, STREAM_SEEK_SET, NULL);
+
+ int width, height;
+ _pStream->Read((char *)&width, 4, &BytesRead);
+ _pStream->Read((char *)&height, 4, &BytesRead);
+ BlockSize -= 8;
+
+ // Isolate RGBA data
+ char *pRGBA = new char[BlockSize];
+ _pStream->Read(pRGBA, BlockSize, &BytesRead);
+
+ if (BytesRead != (ULONG)BlockSize)
+ return E_UNEXPECTED;
+
+ // Convert to BGRA for Windows
+ for (int i = 0; i < BlockSize; i += 4) {
+#define RED_BYTE pRGBA[i]
+#define BLUE_BYTE pRGBA[i + 2]
+
+ char red = RED_BYTE;
+ RED_BYTE = BLUE_BYTE;
+ BLUE_BYTE = red;
+ }
+
+ // Flip vertically (Blender stores it upside-down)
+ unsigned int LineSize = width * 4;
+ char *FlippedImage = new char[BlockSize];
+ for (int i = 0; i < height; i++) {
+ if (0 != memcpy_s(&FlippedImage[(height - i - 1) * LineSize],
+ LineSize,
+ &pRGBA[i * LineSize],
+ LineSize))
+ return E_UNEXPECTED;
+ }
+ delete[] pRGBA;
+ pRGBA = FlippedImage;
+
+ // Create image
+ *phbmp = CreateBitmap(width, height, 1, 32, pRGBA);
+ if (!*phbmp)
+ return E_FAIL;
+ *pdwAlpha = WTSAT_ARGB; // it's actually BGRA, not sure why this works
+
+ // Scale down if required
+ if ((unsigned)width > cx || (unsigned)height > cx) {
+ float scale = 1.0f / (max(width, height) / (float)cx);
+ LONG NewWidth = (LONG)(width * scale);
+ LONG NewHeight = (LONG)(height * scale);
+
+#ifdef _DEBUG
+# if 0
+ MessageBox(0,"Attach now","Debugging",MB_OK);
+# endif
+#endif
+ IWICImagingFactory *pImgFac;
+ hr = CoCreateInstance(
+ CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImgFac));
+
+ IWICBitmap *WICBmp;
+ hr = pImgFac->CreateBitmapFromHBITMAP(*phbmp, 0, WICBitmapUseAlpha, &WICBmp);
+
+ BITMAPINFO bmi = {};
+ bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
+ bmi.bmiHeader.biWidth = NewWidth;
+ bmi.bmiHeader.biHeight = -NewHeight;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 32;
+ bmi.bmiHeader.biCompression = BI_RGB;
+
+ BYTE *pBits;
+ HBITMAP ResizedHBmp = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **)&pBits, NULL, 0);
+ hr = ResizedHBmp ? S_OK : E_OUTOFMEMORY;
+ if (SUCCEEDED(hr)) {
+ IWICBitmapScaler *pIScaler;
+ hr = pImgFac->CreateBitmapScaler(&pIScaler);
+ hr = pIScaler->Initialize(WICBmp, NewWidth, NewHeight, WICBitmapInterpolationModeFant);
+
+ WICRect rect = {0, 0, NewWidth, NewHeight};
+ hr = pIScaler->CopyPixels(&rect, NewWidth * 4, NewWidth * NewHeight * 4, pBits);
+
+ if (SUCCEEDED(hr)) {
+ DeleteObject(*phbmp);
+ *phbmp = ResizedHBmp;
+ }
+ else
+ DeleteObject(ResizedHBmp);
+
+ pIScaler->Release();
+ }
+ WICBmp->Release();
+ pImgFac->Release();
+ }
+ else
+ hr = S_OK;
+ break;
+ }
+ return hr;
+}
diff --git a/source/blender/blendthumb/src/Dll.cpp b/source/blender/blendthumb/src/Dll.cpp
new file mode 100644
index 00000000000..5a6fb4e692c
--- /dev/null
+++ b/source/blender/blendthumb/src/Dll.cpp
@@ -0,0 +1,280 @@
+/*
+ * 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.
+ */
+
+#include <objbase.h>
+#include <shlwapi.h>
+#include <thumbcache.h> // For IThumbnailProvider.
+#include <shlobj.h> // For SHChangeNotify
+#include <new>
+
+extern HRESULT CBlendThumb_CreateInstance(REFIID riid, void **ppv);
+
+#define SZ_CLSID_BLENDTHUMBHANDLER L"{D45F043D-F17F-4e8a-8435-70971D9FA46D}"
+#define SZ_BLENDTHUMBHANDLER L"Blender Thumbnail Handler"
+const CLSID CLSID_BlendThumbHandler = {
+ 0xd45f043d, 0xf17f, 0x4e8a, {0x84, 0x35, 0x70, 0x97, 0x1d, 0x9f, 0xa4, 0x6d}};
+
+typedef HRESULT (*PFNCREATEINSTANCE)(REFIID riid, void **ppvObject);
+struct CLASS_OBJECT_INIT {
+ const CLSID *pClsid;
+ PFNCREATEINSTANCE pfnCreate;
+};
+
+// add classes supported by this module here
+const CLASS_OBJECT_INIT c_rgClassObjectInit[] = {
+ {&CLSID_BlendThumbHandler, CBlendThumb_CreateInstance}};
+
+long g_cRefModule = 0;
+
+// Handle the DLL's module
+HINSTANCE g_hInst = NULL;
+
+// Standard DLL functions
+STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, void *)
+{
+ if (dwReason == DLL_PROCESS_ATTACH) {
+ g_hInst = hInstance;
+ DisableThreadLibraryCalls(hInstance);
+ }
+ return TRUE;
+}
+
+STDAPI DllCanUnloadNow()
+{
+ // Only allow the DLL to be unloaded after all outstanding references have been released
+ return (g_cRefModule == 0) ? S_OK : S_FALSE;
+}
+
+void DllAddRef()
+{
+ InterlockedIncrement(&g_cRefModule);
+}
+
+void DllRelease()
+{
+ InterlockedDecrement(&g_cRefModule);
+}
+
+class CClassFactory : public IClassFactory {
+ public:
+ static HRESULT CreateInstance(REFCLSID clsid,
+ const CLASS_OBJECT_INIT *pClassObjectInits,
+ size_t cClassObjectInits,
+ REFIID riid,
+ void **ppv)
+ {
+ *ppv = NULL;
+ HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
+ for (size_t i = 0; i < cClassObjectInits; i++) {
+ if (clsid == *pClassObjectInits[i].pClsid) {
+ IClassFactory *pClassFactory = new (std::nothrow)
+ CClassFactory(pClassObjectInits[i].pfnCreate);
+ hr = pClassFactory ? S_OK : E_OUTOFMEMORY;
+ if (SUCCEEDED(hr)) {
+ hr = pClassFactory->QueryInterface(riid, ppv);
+ pClassFactory->Release();
+ }
+ break; // match found
+ }
+ }
+ return hr;
+ }
+
+ CClassFactory(PFNCREATEINSTANCE pfnCreate) : _cRef(1), _pfnCreate(pfnCreate)
+ {
+ DllAddRef();
+ }
+
+ // IUnknown
+ IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
+ {
+ static const QITAB qit[] = {QITABENT(CClassFactory, IClassFactory), {0}};
+ return QISearch(this, qit, riid, ppv);
+ }
+
+ IFACEMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&_cRef);
+ }
+
+ IFACEMETHODIMP_(ULONG) Release()
+ {
+ long cRef = InterlockedDecrement(&_cRef);
+ if (cRef == 0) {
+ delete this;
+ }
+ return cRef;
+ }
+
+ // IClassFactory
+ IFACEMETHODIMP CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
+ {
+ return punkOuter ? CLASS_E_NOAGGREGATION : _pfnCreate(riid, ppv);
+ }
+
+ IFACEMETHODIMP LockServer(BOOL fLock)
+ {
+ if (fLock) {
+ DllAddRef();
+ }
+ else {
+ DllRelease();
+ }
+ return S_OK;
+ }
+
+ private:
+ ~CClassFactory()
+ {
+ DllRelease();
+ }
+
+ long _cRef;
+ PFNCREATEINSTANCE _pfnCreate;
+};
+
+STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **ppv)
+{
+ return CClassFactory::CreateInstance(
+ clsid, c_rgClassObjectInit, ARRAYSIZE(c_rgClassObjectInit), riid, ppv);
+}
+
+// A struct to hold the information required for a registry entry
+
+struct REGISTRY_ENTRY {
+ HKEY hkeyRoot;
+ PCWSTR pszKeyName;
+ PCWSTR pszValueName;
+ DWORD dwValueType;
+ PCWSTR pszData;
+};
+
+// Creates a registry key (if needed) and sets the default value of the key
+
+HRESULT CreateRegKeyAndSetValue(const REGISTRY_ENTRY *pRegistryEntry)
+{
+ HKEY hKey;
+ HRESULT hr = HRESULT_FROM_WIN32(RegCreateKeyExW(pRegistryEntry->hkeyRoot,
+ pRegistryEntry->pszKeyName,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_SET_VALUE,
+ NULL,
+ &hKey,
+ NULL));
+ if (SUCCEEDED(hr)) {
+ // All this just to support REG_DWORD...
+ DWORD size;
+ DWORD data;
+ BYTE *lpData = (LPBYTE)pRegistryEntry->pszData;
+ switch (pRegistryEntry->dwValueType) {
+ case REG_SZ:
+ size = ((DWORD)wcslen(pRegistryEntry->pszData) + 1) * sizeof(WCHAR);
+ break;
+ case REG_DWORD:
+ size = sizeof(DWORD);
+ data = (DWORD)pRegistryEntry->pszData;
+ lpData = (BYTE *)&data;
+ break;
+ default:
+ return E_INVALIDARG;
+ }
+
+ hr = HRESULT_FROM_WIN32(RegSetValueExW(
+ hKey, pRegistryEntry->pszValueName, 0, pRegistryEntry->dwValueType, lpData, size));
+ RegCloseKey(hKey);
+ }
+ return hr;
+}
+
+//
+// Registers this COM server
+//
+STDAPI DllRegisterServer()
+{
+ HRESULT hr;
+
+ WCHAR szModuleName[MAX_PATH];
+
+ if (!GetModuleFileNameW(g_hInst, szModuleName, ARRAYSIZE(szModuleName))) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ }
+ else {
+ const REGISTRY_ENTRY rgRegistryEntries[] = {
+ // RootKey KeyName ValueName ValueType Data
+ {HKEY_CURRENT_USER,
+ L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER,
+ NULL,
+ REG_SZ,
+ SZ_BLENDTHUMBHANDLER},
+ {HKEY_CURRENT_USER,
+ L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32",
+ NULL,
+ REG_SZ,
+ szModuleName},
+ {HKEY_CURRENT_USER,
+ L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER L"\\InProcServer32",
+ L"ThreadingModel",
+ REG_SZ,
+ L"Apartment"},
+ {HKEY_CURRENT_USER,
+ L"Software\\Classes\\.blend\\",
+ L"Treatment",
+ REG_DWORD,
+ 0}, // doesn't appear to do anything...
+ {HKEY_CURRENT_USER,
+ L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}",
+ NULL,
+ REG_SZ,
+ SZ_CLSID_BLENDTHUMBHANDLER},
+ };
+
+ hr = S_OK;
+ for (int i = 0; i < ARRAYSIZE(rgRegistryEntries) && SUCCEEDED(hr); i++) {
+ hr = CreateRegKeyAndSetValue(&rgRegistryEntries[i]);
+ }
+ }
+ if (SUCCEEDED(hr)) {
+ // This tells the shell to invalidate the thumbnail cache. This is important because any
+ // .blend files viewed before registering this handler would otherwise show cached blank
+ // thumbnails.
+ SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
+ }
+ return hr;
+}
+
+//
+// Unregisters this COM server
+//
+STDAPI DllUnregisterServer()
+{
+ HRESULT hr = S_OK;
+
+ const PCWSTR rgpszKeys[] = {
+ L"Software\\Classes\\CLSID\\" SZ_CLSID_BLENDTHUMBHANDLER,
+ L"Software\\Classes\\.blend\\ShellEx\\{e357fccd-a995-4576-b01f-234630154e96}"};
+
+ // Delete the registry entries
+ for (int i = 0; i < ARRAYSIZE(rgpszKeys) && SUCCEEDED(hr); i++) {
+ hr = HRESULT_FROM_WIN32(RegDeleteTreeW(HKEY_CURRENT_USER, rgpszKeys[i]));
+ if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) {
+ // If the registry entry has already been deleted, say S_OK.
+ hr = S_OK;
+ }
+ }
+ return hr;
+}
diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c
index d6710b91539..4e44a85443d 100644
--- a/source/blender/blenfont/intern/blf_thumbs.c
+++ b/source/blender/blenfont/intern/blf_thumbs.c
@@ -109,7 +109,7 @@ void BLF_thumb_preview(const char *filename,
font->pos[1] -= font->glyph_cache->ascender * 1.1f;
/* We fallback to default english strings in case not enough chars are available in current
- * font for given translated string (useful in non-latin i18n context, like chinese,
+ * font for given translated string (useful in non-latin i18n context, like Chinese,
* since many fonts will then show nothing but ugly 'missing char' in their preview).
* Does not handle all cases, but much better than nothing.
*/
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index d215f214a6d..2145a673e45 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -79,12 +79,10 @@ struct CustomData_MeshMasks;
struct Depsgraph;
struct MEdge;
struct MFace;
-struct MLoopNorSpaceArray;
struct MVert;
struct Mesh;
struct ModifierData;
struct Object;
-struct PBVH;
struct Scene;
/*
@@ -150,23 +148,6 @@ struct DerivedMesh {
/** Calculate vert and face normals */
void (*calcNormals)(DerivedMesh *dm);
- /** Calculate loop (split) normals */
- void (*calcLoopNormals)(DerivedMesh *dm, const bool use_split_normals, const float split_angle);
-
- /** Calculate loop (split) normals, and returns split loop normal spacearr. */
- void (*calcLoopNormalsSpaceArray)(DerivedMesh *dm,
- const bool use_split_normals,
- const float split_angle,
- struct MLoopNorSpaceArray *r_lnors_spacearr);
-
- void (*calcLoopTangents)(DerivedMesh *dm,
- bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME],
- int tangent_names_count);
-
- /** Recalculates mesh tessellation */
- void (*recalcTessellation)(DerivedMesh *dm);
-
/** Loop tessellation cache (WARNING! Only call inside threading-protected code!) */
void (*recalcLoopTri)(DerivedMesh *dm);
/** accessor functions */
@@ -261,51 +242,6 @@ struct DerivedMesh {
DMFlagMat *(*getGridFlagMats)(DerivedMesh *dm);
unsigned int **(*getGridHidden)(DerivedMesh *dm);
- /** Iterate over each mapped vertex in the derived mesh, calling the
- * given function with the original vert and the mapped vert's new
- * coordinate and normal. For historical reasons the normal can be
- * passed as a float or short array, only one should be non-NULL.
- */
- void (*foreachMappedVert)(DerivedMesh *dm,
- void (*func)(void *userData,
- int index,
- const float co[3],
- const float no_f[3],
- const short no_s[3]),
- void *userData,
- DMForeachFlag flag);
-
- /** Iterate over each mapped edge in the derived mesh, calling the
- * given function with the original edge and the mapped edge's new
- * coordinates.
- */
- void (*foreachMappedEdge)(
- DerivedMesh *dm,
- void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
- void *userData);
-
- /** Iterate over each mapped loop in the derived mesh, calling the given function
- * with the original loop index and the mapped loops's new coordinate and normal.
- */
- void (*foreachMappedLoop)(DerivedMesh *dm,
- void (*func)(void *userData,
- int vertex_index,
- int face_index,
- const float co[3],
- const float no[3]),
- void *userData,
- DMForeachFlag flag);
-
- /** Iterate over each mapped face in the derived mesh, calling the
- * given function with the original face and the mapped face's (or
- * faces') center and normal.
- */
- void (*foreachMappedFaceCenter)(
- DerivedMesh *dm,
- void (*func)(void *userData, int index, const float cent[3], const float no[3]),
- void *userData,
- DMForeachFlag flag);
-
/** Iterate over all vertex points, calling DO_MINMAX with given args.
*
* Also called in Editmode
@@ -319,9 +255,6 @@ struct DerivedMesh {
/** Get vertex location, undefined if index is not valid */
void (*getVertCo)(DerivedMesh *dm, int index, float r_co[3]);
- /** Fill the array (of length .getNumVerts()) with all vertex locations */
- void (*getVertCos)(DerivedMesh *dm, float (*r_cos)[3]);
-
/** Get smooth vertex normal, undefined if index is not valid */
void (*getVertNo)(DerivedMesh *dm, int index, float r_no[3]);
void (*getPolyNo)(DerivedMesh *dm, int index, float r_no[3]);
@@ -330,10 +263,6 @@ struct DerivedMesh {
*/
const struct MeshElemMap *(*getPolyMap)(struct Object *ob, DerivedMesh *dm);
- /** Get the BVH used for paint modes
- */
- struct PBVH *(*getPBVH)(struct Object *ob, DerivedMesh *dm);
-
/** Release reference to the DerivedMesh. This function decides internally
* if the DerivedMesh will be freed, or cached for later use. */
void (*release)(DerivedMesh *dm);
@@ -372,14 +301,6 @@ void DM_from_template(DerivedMesh *dm,
*/
int DM_release(DerivedMesh *dm);
-/** utility function to convert a DerivedMesh to a Mesh
- */
-void DM_to_mesh(DerivedMesh *dm,
- struct Mesh *me,
- struct Object *ob,
- const struct CustomData_MeshMasks *mask,
- bool take_ownership);
-
void DM_set_only_copy(DerivedMesh *dm, const struct CustomData_MeshMasks *mask);
/* adds a vertex/edge/face custom data layer to a DerivedMesh, optionally
@@ -446,8 +367,6 @@ DerivedMesh *mesh_create_derived_render(struct Depsgraph *depsgraph,
const struct CustomData_MeshMasks *dataMask);
/* same as above but wont use render settings */
-DerivedMesh *mesh_create_derived(struct Mesh *me, float (*vertCos)[3]);
-
struct Mesh *editbmesh_get_eval_cage(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *,
@@ -464,7 +383,7 @@ struct Mesh *editbmesh_get_eval_cage_and_final(struct Depsgraph *depsgraph,
const struct CustomData_MeshMasks *dataMask,
struct Mesh **r_final);
-float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *r_numVerts))[3];
+float (*editbmesh_vert_coords_alloc(struct BMEditMesh *em, int *r_vert_len))[3];
bool editbmesh_modifier_is_enabled(struct Scene *scene,
struct ModifierData *md,
bool has_prev_mesh);
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index dab76fb79f1..dce6f337885 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -24,7 +24,6 @@
*/
struct Depsgraph;
struct ListBase;
-struct Main;
struct Object;
struct ParticleSystem;
struct Path;
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index fa8e294bdc1..a2a14011595 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -34,7 +34,6 @@ struct KeyingSet;
struct ListBase;
struct Main;
struct NlaKeyframingContext;
-struct PathResolvedRNA;
struct PointerRNA;
struct PropertyRNA;
struct ReportList;
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 99c6bb405b5..3beae7a1f9d 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -25,7 +25,6 @@
struct Bone;
struct Depsgraph;
-struct GHash;
struct ListBase;
struct Main;
struct Object;
@@ -78,6 +77,8 @@ struct bArmature *BKE_armature_copy(struct Main *bmain, const struct bArmature *
void BKE_armature_copy_bone_transforms(struct bArmature *armature_dst,
const struct bArmature *armature_src);
+void BKE_armature_transform(struct bArmature *arm, const float mat[4][4], const bool do_props);
+
/* Bounding box. */
struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
@@ -100,7 +101,7 @@ float distfactor_to_bone(
void BKE_armature_where_is(struct bArmature *arm);
void BKE_armature_where_is_bone(struct Bone *bone,
- struct Bone *prevbone,
+ const struct Bone *bone_parent,
const bool use_recursion);
void BKE_pose_clear_pointers(struct bPose *pose);
void BKE_pose_remap_bone_pointers(struct bArmature *armature, struct bPose *pose);
diff --git a/source/blender/blenkernel/BKE_blender_undo.h b/source/blender/blenkernel/BKE_blender_undo.h
index 6c2221326e9..7392d3947a2 100644
--- a/source/blender/blenkernel/BKE_blender_undo.h
+++ b/source/blender/blenkernel/BKE_blender_undo.h
@@ -26,7 +26,6 @@ extern "C" {
struct Main;
struct MemFileUndoData;
-struct Scene;
struct bContext;
#define BKE_UNDO_STR_MAX 64
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index 0c55ae8ee83..65086f57616 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -27,7 +27,7 @@
* \note Use #STRINGIFY() rather than defining with quotes.
*/
#define BLENDER_VERSION 281
-#define BLENDER_SUBVERSION 2
+#define BLENDER_SUBVERSION 5
/** Several breakages with 280, e.g. collections vs layers. */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
@@ -37,6 +37,8 @@
#define BLENDER_VERSION_CHAR
/** alpha/beta/rc/release, docs use this. */
#define BLENDER_VERSION_CYCLE alpha
+/** Optionally set to 1,2,... for example to to get alpha1 or rc2. */
+#define BLENDER_VERSION_CYCLE_NUMBER
/** Defined in from blender.c */
extern char versionstr[];
diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h
index eeebfe1f2f6..26ab7f8ba0c 100644
--- a/source/blender/blenkernel/BKE_brush.h
+++ b/source/blender/blenkernel/BKE_brush.h
@@ -28,8 +28,6 @@ struct Brush;
struct ImBuf;
struct ImagePool;
struct Main;
-struct Material;
-struct Paint;
struct Scene;
struct ToolSettings;
struct UnifiedPaintSettings;
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index c88a64097bb..fdcb4066482 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -31,7 +31,6 @@
*/
struct BMEditMesh;
-struct DerivedMesh;
struct MFace;
struct MVert;
struct Mesh;
@@ -93,19 +92,18 @@ typedef struct BVHTreeFromMesh {
*
* free_bvhtree_from_mesh should be called when the tree is no longer needed.
*/
-BVHTree *bvhtree_from_editmesh_verts(BVHTreeFromEditMesh *data,
- struct BMEditMesh *em,
- float epsilon,
- int tree_type,
- int axis,
- BVHCache **bvh_cache);
+BVHTree *bvhtree_from_editmesh_verts(
+ BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis);
+
BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const BLI_bitmap *mask,
int verts_num_active,
float epsilon,
int tree_type,
- int axis);
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache);
BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -115,21 +113,22 @@ BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data,
int verts_num_active,
float epsilon,
int tree_type,
- int axis);
-
-BVHTree *bvhtree_from_editmesh_edges(BVHTreeFromEditMesh *data,
- struct BMEditMesh *em,
- float epsilon,
- int tree_type,
- int axis,
- BVHCache **bvh_cache);
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache);
+
+BVHTree *bvhtree_from_editmesh_edges(
+ BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis);
+
BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const BLI_bitmap *edges_mask,
int edges_num_active,
float epsilon,
int tree_type,
- int axis);
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache);
BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -141,7 +140,9 @@ BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data,
int edges_num_active,
float epsilon,
int tree_type,
- int axis);
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache);
BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -153,14 +154,13 @@ BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data,
int numFaces_active,
float epsilon,
int tree_type,
- int axis);
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache);
+
+BVHTree *bvhtree_from_editmesh_looptri(
+ BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis);
-BVHTree *bvhtree_from_editmesh_looptri(BVHTreeFromEditMesh *data,
- struct BMEditMesh *em,
- float epsilon,
- int tree_type,
- int axis,
- BVHCache **bvhCache);
BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const BLI_bitmap *mask,
@@ -168,7 +168,8 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
float epsilon,
int tree_type,
int axis,
- BVHCache **bvhCache);
+ const int bvh_cache_type,
+ BVHCache **bvh_cache);
BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -182,13 +183,21 @@ BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
int looptri_num_active,
float epsilon,
int tree_type,
- int axis);
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache);
BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
struct Mesh *mesh,
const int type,
const int tree_type);
+BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
+ struct BMEditMesh *em,
+ const int tree_type,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache);
+
/**
* Frees data allocated by a call to bvhtree_from_mesh_*.
*/
diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h
index 257975e3c17..c8393fd3666 100644
--- a/source/blender/blenkernel/BKE_cachefile.h
+++ b/source/blender/blenkernel/BKE_cachefile.h
@@ -33,7 +33,6 @@ struct CacheReader;
struct Depsgraph;
struct Main;
struct Object;
-struct Scene;
void BKE_cachefiles_init(void);
void BKE_cachefiles_exit(void);
diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h
index caed4959eff..da80b3d5032 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -32,14 +32,12 @@ extern "C" {
struct Camera;
struct Depsgraph;
-struct GPUFXSettings;
struct Main;
struct Object;
struct RegionView3D;
struct RenderData;
struct Scene;
struct View3D;
-struct ViewLayer;
struct rctf;
/* Camera Datablock */
diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h
index 08d53bf0e21..50af6c876b4 100644
--- a/source/blender/blenkernel/BKE_cdderivedmesh.h
+++ b/source/blender/blenkernel/BKE_cdderivedmesh.h
@@ -33,9 +33,7 @@
struct BMEditMesh;
struct CustomData_MeshMasks;
struct DerivedMesh;
-struct MLoopNorSpaceArray;
struct Mesh;
-struct Object;
/* creates a new CDDerivedMesh */
struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, int numLoops, int numPolys);
@@ -51,79 +49,16 @@ struct DerivedMesh *CDDM_from_mesh_ex(struct Mesh *mesh,
eCDAllocType alloctype,
const struct CustomData_MeshMasks *mask);
-struct DerivedMesh *CDDM_from_bmesh(struct BMesh *bm, const bool use_mdisps);
-
/* creates a CDDerivedMesh from the given BMEditMesh */
-DerivedMesh *CDDM_from_editbmesh(struct BMEditMesh *em,
- const bool use_mdisps,
- const bool use_tessface);
-
-/* creates a CDDerivedMesh from the given curve object */
-struct DerivedMesh *CDDM_from_curve(struct Object *ob);
-
-/* creates a CDDerivedMesh from the given curve object and specified dispbase */
-/* useful for OrcoDM creation for curves with constructive modifiers */
-DerivedMesh *CDDM_from_curve_displist(struct Object *ob, struct ListBase *dispbase);
+DerivedMesh *CDDM_from_editbmesh(struct BMEditMesh *em, const bool use_mdisps);
/* Copies the given DerivedMesh with verts, faces & edges stored as
* custom element data.
*/
struct DerivedMesh *CDDM_copy(struct DerivedMesh *dm);
-/* creates a CDDerivedMesh with the same layer stack configuration as the
- * given DerivedMesh and containing the requested numbers of elements.
- * elements are initialized to all zeros
- */
-struct DerivedMesh *CDDM_from_template_ex(struct DerivedMesh *source,
- int numVerts,
- int numEdges,
- int numFaces,
- int numLoops,
- int numPolys,
- const struct CustomData_MeshMasks *mask);
-struct DerivedMesh *CDDM_from_template(struct DerivedMesh *source,
- int numVerts,
- int numEdges,
- int numFaces,
- int numLoops,
- int numPolys);
-
-/* applies vertex coordinates or normals to a CDDerivedMesh. if the MVert
- * layer is a referenced layer, it will be duplicate to not overwrite the
- * original
- */
-void CDDM_apply_vert_coords(struct DerivedMesh *cddm, float (*vertCoords)[3]);
-void CDDM_apply_vert_normals(struct DerivedMesh *cddm, short (*vertNormals)[3]);
-
-/* recalculates vertex and face normals for a CDDerivedMesh
- */
-void CDDM_calc_normals_mapping_ex(struct DerivedMesh *dm, const bool only_face_normals);
-void CDDM_calc_normals_mapping(struct DerivedMesh *dm);
-void CDDM_calc_normals(struct DerivedMesh *dm);
-
-void CDDM_calc_loop_normals(struct DerivedMesh *dm,
- const bool use_split_normals,
- const float split_angle);
-void CDDM_calc_loop_normals_spacearr(struct DerivedMesh *dm,
- const bool use_split_normals,
- const float split_angle,
- struct MLoopNorSpaceArray *r_lnors_spacearr);
-
-/* reconstitute face triangulation */
-void CDDM_recalc_tessellation(struct DerivedMesh *dm);
-void CDDM_recalc_tessellation_ex(struct DerivedMesh *dm, const bool do_face_nor_cpy);
-
void CDDM_recalc_looptri(struct DerivedMesh *dm);
-/* lowers the number of vertices/edges/faces in a CDDerivedMesh
- * the layer data stays the same size
- */
-void CDDM_lower_num_verts(struct DerivedMesh *dm, int numVerts);
-void CDDM_lower_num_edges(struct DerivedMesh *dm, int numEdges);
-void CDDM_lower_num_loops(struct DerivedMesh *dm, int numLoops);
-void CDDM_lower_num_polys(struct DerivedMesh *dm, int numPolys);
-void CDDM_lower_num_tessfaces(DerivedMesh *dm, int numTessFaces);
-
/* vertex/edge/face access functions
* should always succeed if index is within bounds
* note these return pointers - any change modifies the internals of the mesh
@@ -145,13 +80,4 @@ struct MFace *CDDM_get_tessfaces(struct DerivedMesh *dm);
struct MLoop *CDDM_get_loops(struct DerivedMesh *dm);
struct MPoly *CDDM_get_polys(struct DerivedMesh *dm);
-/* Assigns news m*** layers to the cddm. Note that you must handle
- * freeing the old ones yourself. Also you must ensure dm->num****Data
- * is correct.*/
-void CDDM_set_mvert(struct DerivedMesh *dm, struct MVert *mvert);
-void CDDM_set_medge(struct DerivedMesh *dm, struct MEdge *medge);
-void CDDM_set_mface(struct DerivedMesh *dm, struct MFace *mface);
-void CDDM_set_mloop(struct DerivedMesh *dm, struct MLoop *mloop);
-void CDDM_set_mpoly(struct DerivedMesh *dm, struct MPoly *mpoly);
-
#endif
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 43df78c33e4..01f94c39215 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -29,7 +29,6 @@
struct ClothModifierData;
struct CollisionModifierData;
struct Depsgraph;
-struct MFace;
struct Mesh;
struct Object;
struct Scene;
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 0ab101f065d..0d33d86ec16 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -35,8 +35,6 @@ extern "C" {
struct BLI_Iterator;
struct Base;
struct Collection;
-struct Depsgraph;
-struct ID;
struct Main;
struct Object;
struct Scene;
@@ -72,13 +70,9 @@ struct Collection *BKE_collection_duplicate(struct Main *bmain,
const bool do_hierarchy,
const bool do_objects,
const bool do_obdata);
-struct Collection *BKE_collection_copy_master(struct Main *bmain,
- struct Collection *collection,
- const int flag);
/* Master Collection for Scene */
-struct Collection *BKE_collection_master(const struct Scene *scene);
struct Collection *BKE_collection_master_add(void);
struct Scene *BKE_collection_master_scene_search(const struct Main *bmain,
const struct Collection *master_collection);
@@ -227,7 +221,7 @@ void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter);
bool is_scene_collection = (_scene) != NULL; \
\
if (_scene) { \
- _instance_next = BKE_collection_master(_scene); \
+ _instance_next = _scene->master_collection; \
} \
else { \
_instance_next = (_bmain)->collections.first; \
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index 291502a0c28..5d7a5094eb5 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -37,11 +37,9 @@
struct Collection;
struct CollisionModifierData;
struct Depsgraph;
-struct MFace;
struct MVert;
struct MVertTri;
struct Object;
-struct Scene;
////////////////////////////////////////
// used for collisions in collision.c
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 755a155653b..105f8e82343 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -33,7 +33,6 @@ extern "C" {
struct ARegion;
struct Base;
-struct Brush;
struct CacheFile;
struct Collection;
struct Depsgraph;
@@ -59,7 +58,6 @@ struct Text;
struct ToolSettings;
struct View3D;
struct ViewLayer;
-struct ViewRender;
struct bGPDframe;
struct bGPDlayer;
struct bGPdata;
@@ -98,7 +96,7 @@ typedef struct bContextStore {
/* for the context's rna mode enum
* keep aligned with data_mode_strings in context.c */
-enum eContextObjectMode {
+typedef enum eContextObjectMode {
CTX_MODE_EDIT_MESH = 0,
CTX_MODE_EDIT_CURVE,
CTX_MODE_EDIT_SURFACE,
@@ -117,7 +115,7 @@ enum eContextObjectMode {
CTX_MODE_EDIT_GPENCIL,
CTX_MODE_SCULPT_GPENCIL,
CTX_MODE_WEIGHT_GPENCIL,
-};
+} eContextObjectMode;
#define CTX_MODE_NUM (CTX_MODE_WEIGHT_GPENCIL + 1)
/* Context */
@@ -239,7 +237,7 @@ bool CTX_data_dir(const char *member);
#define CTX_DATA_BEGIN_WITH_ID(C, Type, instance, member, Type_id, instance_id) \
CTX_DATA_BEGIN (C, Type, instance, member) \
- Type_id instance_id = ctx_link->ptr.id.data;
+ Type_id instance_id = (Type_id)ctx_link->ptr.owner_id;
int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBase *));
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 51ff4673aba..be49ca150b2 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -26,15 +26,12 @@
struct BezTriple;
struct Curve;
struct Depsgraph;
-struct EditNurb;
struct GHash;
-struct LinkNode;
struct ListBase;
struct Main;
struct Nurb;
struct Object;
struct Path;
-struct Scene;
struct TextBox;
struct rctf;
@@ -124,11 +121,22 @@ void BKE_curve_nurb_vert_active_set(struct Curve *cu, const struct Nurb *nu, con
bool BKE_curve_nurb_vert_active_get(struct Curve *cu, struct Nurb **r_nu, void **r_vert);
void BKE_curve_nurb_vert_active_validate(struct Curve *cu);
-float (*BKE_curve_nurbs_vertexCos_get(struct ListBase *lb, int *r_numVerts))[3];
-void BK_curve_nurbs_vertexCos_apply(struct ListBase *lb, float (*vertexCos)[3]);
+float (*BKE_curve_nurbs_vert_coords_alloc(struct ListBase *lb, int *r_vert_len))[3];
+void BKE_curve_nurbs_vert_coords_get(struct ListBase *lb, float (*vert_coords)[3], int vert_len);
-float (*BKE_curve_nurbs_keyVertexCos_get(struct ListBase *lb, float *key))[3];
-void BKE_curve_nurbs_keyVertexTilts_apply(struct ListBase *lb, float *key);
+void BKE_curve_nurbs_vert_coords_apply_with_mat4(struct ListBase *lb,
+ const float (*vert_coords)[3],
+ const float mat[4][4],
+ const bool constrain_2d);
+
+void BKE_curve_nurbs_vert_coords_apply(struct ListBase *lb,
+ const float (*vert_coords)[3],
+ const bool constrain_2d);
+
+float (*BKE_curve_nurbs_key_vert_coords_alloc(struct ListBase *lb,
+ float *key,
+ int *r_vert_len))[3];
+void BKE_curve_nurbs_key_vert_tilts_apply(struct ListBase *lb, float *key);
void BKE_curve_editNurb_keyIndex_delCV(struct GHash *keyindex, const void *cv);
void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex);
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index c57639a8193..cfacbfe0a21 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -49,9 +49,7 @@ enum {
/* prototypes */
struct Depsgraph;
-struct LinkNode;
struct ListBase;
-struct Main;
struct Mesh;
struct Object;
struct Scene;
diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h
index c4f05d404ce..734bfbc019a 100644
--- a/source/blender/blenkernel/BKE_dynamicpaint.h
+++ b/source/blender/blenkernel/BKE_dynamicpaint.h
@@ -25,9 +25,7 @@ struct Depsgraph;
struct DynamicPaintCanvasSettings;
struct DynamicPaintModifierData;
struct DynamicPaintRuntime;
-struct Main;
struct Scene;
-struct ViewLayer;
/* Actual surface point */
typedef struct PaintSurfaceData {
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index b7280c702d2..062968eddfc 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -31,7 +31,6 @@
struct BMLoop;
struct BMesh;
struct Depsgraph;
-struct DerivedMesh;
struct EditMeshData;
struct Mesh;
struct MeshStatVis;
@@ -79,7 +78,7 @@ typedef struct BMEditMesh {
} BMEditMesh;
/* editmesh.c */
-void BKE_editmesh_tessface_calc(BMEditMesh *em);
+void BKE_editmesh_looptri_calc(BMEditMesh *em);
BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate);
BMEditMesh *BKE_editmesh_copy(BMEditMesh *em);
BMEditMesh *BKE_editmesh_from_object(struct Object *ob);
@@ -88,7 +87,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];
+float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3];
void BKE_editmesh_lnorspace_update(BMEditMesh *em);
void BKE_editmesh_ensure_autosmooth(BMEditMesh *em);
@@ -98,7 +97,7 @@ void BKE_editmesh_statvis_calc(BMEditMesh *em,
struct EditMeshData *emd,
const struct MeshStatVis *statvis);
-float (*BKE_editmesh_vertexCos_get(
- struct Depsgraph *depsgraph, struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3];
+float (*BKE_editmesh_vert_coords_alloc(
+ struct Depsgraph *depsgraph, struct BMEditMesh *em, struct Scene *scene, int *r_vert_len))[3];
#endif /* __BKE_EDITMESH_H__ */
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 4c1a115eb23..5be9a35b168 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -89,6 +89,9 @@ struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver);
void driver_variables_copy(struct ListBase *dst_list, const struct ListBase *src_list);
+void BKE_driver_target_matrix_to_rot_channels(
+ float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]);
+
void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar);
void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar);
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index c544c065a70..b4f636199f8 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -24,31 +24,40 @@
* \ingroup bke
*/
-struct Scene;
-struct ArrayGpencilModifierData;
struct BoundBox;
struct Brush;
struct CurveMapping;
struct Depsgraph;
-struct GpencilModifierData;
-struct LatticeGpencilModifierData;
struct ListBase;
struct Main;
struct Material;
struct Object;
-struct SimplifyGpencilModifierData;
struct ToolSettings;
struct bDeformGroup;
struct bGPDframe;
struct bGPDlayer;
-struct bGPDpalette;
-struct bGPDpalettecolor;
struct bGPDspoint;
struct bGPDstroke;
struct bGPdata;
struct MDeformVert;
-struct MDeformWeight;
+
+#define GPENCIL_SIMPLIFY(scene) ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE))
+#define GPENCIL_SIMPLIFY_ONPLAY(playing) \
+ (((playing == true) && (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY)) || \
+ ((scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ON_PLAY) == 0))
+#define GPENCIL_SIMPLIFY_FILL(scene, playing) \
+ ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
+ (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FILL)))
+#define GPENCIL_SIMPLIFY_MODIF(scene, playing) \
+ ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
+ (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_MODIFIER)))
+#define GPENCIL_SIMPLIFY_FX(scene, playing) \
+ ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
+ (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_FX)))
+#define GPENCIL_SIMPLIFY_BLEND(scene, playing) \
+ ((GPENCIL_SIMPLIFY_ONPLAY(playing) && (GPENCIL_SIMPLIFY(scene)) && \
+ (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_BLEND)))
struct GPUBatch;
struct GPUVertBuf;
@@ -134,7 +143,7 @@ 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);
-bool BKE_gpencil_free_frame_runtime_data(struct bGPDframe *derived_gpf);
+bool BKE_gpencil_free_frame_runtime_data(struct bGPDframe *gpf_eval);
void BKE_gpencil_free(struct bGPdata *gpd, bool free_all);
void BKE_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd);
@@ -220,13 +229,14 @@ struct bGPDlayer *BKE_gpencil_layer_get_index(struct bGPdata *gpd,
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);
+void BKE_gpencil_layer_autolock_set(struct bGPdata *gpd);
/* Brush */
struct Material *BKE_gpencil_brush_material_get(struct Brush *brush);
void BKE_gpencil_brush_material_set(struct Brush *brush, struct Material *material);
/* Object */
-struct Material *BKE_gpencil_object_material_ensure_active(struct Main *bmain, struct Object *ob);
+struct Material *BKE_gpencil_object_material_ensure_active(struct Object *ob);
struct Material *BKE_gpencil_object_material_ensure_from_brush(struct Main *bmain,
struct Object *ob,
struct Brush *brush);
@@ -250,8 +260,7 @@ struct Material *BKE_gpencil_object_material_ensure_from_active_input_toolsettin
struct Material *BKE_gpencil_object_material_ensure_from_active_input_brush(struct Main *bmain,
struct Object *ob,
struct Brush *brush);
-struct Material *BKE_gpencil_object_material_ensure_from_active_input_material(struct Main *bmain,
- struct Object *ob);
+struct Material *BKE_gpencil_object_material_ensure_from_active_input_material(struct Object *ob);
/* object boundbox */
bool BKE_gpencil_data_minmax(const struct bGPdata *gpd, float r_min[3], float r_max[3]);
@@ -324,7 +333,8 @@ void BKE_gpencil_convert_curve(struct Main *bmain,
struct Object *ob_gp,
struct Object *ob_cu,
const bool gpencil_lines,
- const bool use_collections);
+ const bool use_collections,
+ const bool only_stroke);
extern void (*BKE_gpencil_batch_cache_dirty_tag_cb)(struct bGPdata *gpd);
extern void (*BKE_gpencil_batch_cache_free_cb)(struct bGPdata *gpd);
diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h
index 373efadad55..36f38996c36 100644
--- a/source/blender/blenkernel/BKE_gpencil_modifier.h
+++ b/source/blender/blenkernel/BKE_gpencil_modifier.h
@@ -24,23 +24,16 @@
#include "BLI_compiler_attrs.h"
#include "BKE_customdata.h"
-struct BMEditMesh;
-struct DepsNodeHandle;
struct Depsgraph;
-struct DerivedMesh;
struct GpencilModifierData;
struct ID;
struct ListBase;
struct Main;
-struct Mesh;
struct ModifierUpdateDepsgraphContext;
struct Object;
struct Scene;
-struct ViewLayer;
-struct bArmature;
/* NOTE: bakeModifier() called from UI:
* needs to create new databloc-ks, hence the need for this. */
-struct bContext;
struct bGPDframe;
struct bGPDlayer;
struct bGPDstroke;
diff --git a/source/blender/blenkernel/BKE_image_save.h b/source/blender/blenkernel/BKE_image_save.h
index 26c377a2574..8dfece944ff 100644
--- a/source/blender/blenkernel/BKE_image_save.h
+++ b/source/blender/blenkernel/BKE_image_save.h
@@ -31,7 +31,6 @@ extern "C" {
struct Image;
struct Main;
-struct RenderResult;
struct ReportList;
struct Scene;
diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h
index 58ad3f6230d..477a22b07bb 100644
--- a/source/blender/blenkernel/BKE_key.h
+++ b/source/blender/blenkernel/BKE_key.h
@@ -31,7 +31,6 @@ struct ListBase;
struct Main;
struct Mesh;
struct Object;
-struct WeightsArrayCache;
/* Kernel prototypes */
#ifdef __cplusplus
@@ -92,13 +91,17 @@ void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb,
float (*r_polynors)[3],
float (*r_loopnors)[3]);
-void BKE_keyblock_update_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]);
+void BKE_keyblock_update_from_vertcos(struct Object *ob,
+ struct KeyBlock *kb,
+ const float (*vertCos)[3]);
void BKE_keyblock_convert_from_vertcos(struct Object *ob,
struct KeyBlock *kb,
- float (*vertCos)[3]);
+ const float (*vertCos)[3]);
float (*BKE_keyblock_convert_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3];
-void BKE_keyblock_update_from_offset(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]);
+void BKE_keyblock_update_from_offset(struct Object *ob,
+ struct KeyBlock *kb,
+ const float (*ofs)[3]);
/* other management */
bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index);
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index c4173cd867e..a3befa6f3bb 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -58,7 +58,7 @@ void outside_lattice(struct Lattice *lt);
void curve_deform_verts(struct Object *cuOb,
struct Object *target,
- float (*vertexCos)[3],
+ float (*vert_coords)[3],
int numVerts,
struct MDeformVert *dvert,
const int defgrp_index,
@@ -73,14 +73,14 @@ void curve_deform_vector(struct Object *cuOb,
void lattice_deform_verts(struct Object *laOb,
struct Object *target,
struct Mesh *mesh,
- float (*vertexCos)[3],
+ float (*vert_coords)[3],
int numVerts,
const char *vgroup,
float influence);
void armature_deform_verts(struct Object *armOb,
struct Object *target,
const struct Mesh *mesh,
- float (*vertexCos)[3],
+ float (*vert_coords)[3],
float (*defMats)[3][3],
int numVerts,
int deformflag,
@@ -88,8 +88,12 @@ void armature_deform_verts(struct Object *armOb,
const char *defgrp_name,
struct bGPDstroke *gps);
-float (*BKE_lattice_vertexcos_get(struct Object *ob, int *r_numVerts))[3];
-void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3]);
+float (*BKE_lattice_vert_coords_alloc(const struct Lattice *lt, int *r_vert_len))[3];
+void BKE_lattice_vert_coords_get(const struct Lattice *lt, float (*vert_coords)[3]);
+void BKE_lattice_vert_coords_apply_with_mat4(struct Lattice *lt,
+ const float (*vert_coords)[3],
+ const float mat[4][4]);
+void BKE_lattice_vert_coords_apply(struct Lattice *lt, const float (*vert_coords)[3]);
void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index daac35a1196..eb65b7641e1 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -37,17 +37,12 @@ extern "C" {
struct Base;
struct Collection;
struct Depsgraph;
-struct ID;
-struct IDProperty;
struct LayerCollection;
-struct ListBase;
struct Main;
struct Object;
-struct RenderEngine;
struct Scene;
struct View3D;
struct ViewLayer;
-struct WorkSpace;
struct ViewLayer *BKE_view_layer_default_view(const struct Scene *scene);
struct ViewLayer *BKE_view_layer_default_render(const struct Scene *scene);
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index c0ac71f9c96..261416dc025 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -46,17 +46,14 @@ extern "C" {
* except in some specific cases requiring advanced (and potentially dangerous) handling.
*/
-struct BlendThumbnail;
struct GHash;
struct ID;
-struct ImBuf;
struct Library;
struct ListBase;
struct Main;
struct PointerRNA;
struct PropertyRNA;
struct bContext;
-struct wmWindowManager;
size_t BKE_libblock_get_alloc_info(short type, const char **name);
void *BKE_libblock_alloc_notest(short type) ATTR_WARN_UNUSED_RESULT;
@@ -117,10 +114,7 @@ enum {
LIB_ID_CREATE_NO_DEG_TAG | LIB_ID_COPY_NO_PREVIEW | LIB_ID_COPY_CACHES,
};
-void BKE_libblock_copy_ex(struct Main *bmain,
- const struct ID *id,
- struct ID **r_newid,
- const int flag);
+void BKE_libblock_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, int flag);
void *BKE_libblock_copy(struct Main *bmain, const struct ID *id) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
/* Special version. sued by datablock localization. */
diff --git a/source/blender/blenkernel/BKE_library_override.h b/source/blender/blenkernel/BKE_library_override.h
index 5440b0ebe63..93b2355ce55 100644
--- a/source/blender/blenkernel/BKE_library_override.h
+++ b/source/blender/blenkernel/BKE_library_override.h
@@ -35,8 +35,8 @@ bool BKE_override_library_is_enabled(void);
struct IDOverrideLibrary *BKE_override_library_init(struct ID *local_id, struct ID *reference_id);
void BKE_override_library_copy(struct ID *dst_id, const struct ID *src_id);
-void BKE_override_library_clear(struct IDOverrideLibrary *override);
-void BKE_override_library_free(struct IDOverrideLibrary **override);
+void BKE_override_library_clear(struct IDOverrideLibrary *override, const bool do_id_user);
+void BKE_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user);
struct ID *BKE_override_library_create_from_id(struct Main *bmain, struct ID *reference_id);
bool BKE_override_library_create_from_tag(struct Main *bmain);
diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_library_remap.h
index d51bc5c2bce..784e1a570c5 100644
--- a/source/blender/blenkernel/BKE_library_remap.h
+++ b/source/blender/blenkernel/BKE_library_remap.h
@@ -25,6 +25,8 @@ extern "C" {
#include "BLI_compiler_attrs.h"
+struct wmWindowManager;
+
/* BKE_libblock_free, delete are declared in BKE_library.h for convenience. */
/* Also IDRemap->flag. */
@@ -83,7 +85,7 @@ void BKE_libblock_relink_ex(struct Main *bmain,
void *idv,
void *old_idv,
void *new_idv,
- const bool us_min_never_null) ATTR_NONNULL(1, 2);
+ const short remap_flags) ATTR_NONNULL(1, 2);
void BKE_libblock_relink_to_newid(struct ID *id) ATTR_NONNULL();
diff --git a/source/blender/blenkernel/BKE_light.h b/source/blender/blenkernel/BKE_light.h
index 72bd5857526..e060f587afe 100644
--- a/source/blender/blenkernel/BKE_light.h
+++ b/source/blender/blenkernel/BKE_light.h
@@ -32,7 +32,6 @@ extern "C" {
struct Light;
struct Main;
-struct Scene;
void BKE_light_init(struct Light *la);
struct Light *BKE_light_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h
index 79579b43446..b8950e5df88 100644
--- a/source/blender/blenkernel/BKE_linestyle.h
+++ b/source/blender/blenkernel/BKE_linestyle.h
@@ -38,7 +38,6 @@ extern "C" {
struct ColorBand;
struct Main;
-struct Object;
struct ViewLayer;
struct bContext;
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 1c987d5eb8e..1b2e8bcbf42 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -40,7 +40,6 @@ extern "C" {
struct BLI_mempool;
struct BlendThumbnail;
-struct Depsgraph;
struct GHash;
struct GSet;
struct ImBuf;
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index f87c73e35a2..47644ce82e9 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -38,7 +38,6 @@ struct MaskSplinePoint;
struct MaskSplinePointUW;
struct MovieClip;
struct MovieClipUser;
-struct Scene;
/* mask_ops.c */
typedef enum {
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 5bb69c7166e..7ff9c4e6376 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -38,6 +38,7 @@ struct bNode;
/* materials */
void init_def_material(void);
+void BKE_material_gpencil_default_free(void);
void BKE_material_free(struct Material *ma);
void test_object_materials(struct Main *bmain, struct Object *ob, struct ID *id);
void test_all_objects_materials(struct Main *bmain, struct ID *id);
@@ -46,6 +47,7 @@ void BKE_material_resize_object(struct Main *bmain,
const short totcol,
bool do_id_user);
void BKE_material_init(struct Material *ma);
+void BKE_material_gpencil_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,
@@ -92,6 +94,7 @@ bool BKE_object_material_slot_add(struct Main *bmain, struct Object *ob);
bool BKE_object_material_slot_remove(struct Main *bmain, struct Object *ob);
bool BKE_object_material_slot_used(struct ID *id, short actcol);
+struct Material *BKE_material_gpencil_get(struct Object *ob, short act);
struct MaterialGPencilStyle *BKE_material_gpencil_settings_get(struct Object *ob, short act);
void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
@@ -104,9 +107,8 @@ void BKE_material_append_id(struct Main *bmain, struct ID *id, struct Material *
struct Material *BKE_material_pop_id(struct Main *bmain,
struct ID *id,
/* index is an int because of RNA. */
- int index,
- bool update_data);
-void BKE_material_clear_id(struct Main *bmain, struct ID *id, bool update_data);
+ int index);
+void BKE_material_clear_id(struct Main *bmain, struct ID *id);
/* rendering */
void ramp_blend(int type, float r_col[3], const float fac, const float col[3]);
@@ -124,6 +126,7 @@ struct Depsgraph;
void BKE_material_eval(struct Depsgraph *depsgraph, struct Material *material);
extern struct Material defmaterial;
+extern struct Material defgpencil_material;
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index b582e88f9cb..5447fd00866 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -63,7 +63,7 @@ bool BKE_mball_minmax_ex(const struct MetaBall *mb,
bool BKE_mball_minmax(const struct MetaBall *mb, float min[3], float max[3]);
bool BKE_mball_center_median(const struct MetaBall *mb, float r_cent[3]);
bool BKE_mball_center_bounds(const struct MetaBall *mb, float r_cent[3]);
-void BKE_mball_transform(struct MetaBall *mb, float mat[4][4], const bool do_props);
+void BKE_mball_transform(struct MetaBall *mb, const float mat[4][4], const bool do_props);
void BKE_mball_translate(struct MetaBall *mb, const float offset[3]);
struct MetaElem *BKE_mball_element_add(struct MetaBall *mb, const int type);
diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h
index ab8fbc44caf..39740458f2f 100644
--- a/source/blender/blenkernel/BKE_mball_tessellate.h
+++ b/source/blender/blenkernel/BKE_mball_tessellate.h
@@ -20,7 +20,6 @@
* \ingroup bke
*/
struct Depsgraph;
-struct Main;
struct Object;
struct Scene;
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 94d118bde36..12978e46327 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -53,13 +53,11 @@ struct MLoopTri;
struct MLoopUV;
struct MPoly;
struct MVert;
-struct MVertTri;
struct Main;
struct MemArena;
struct Mesh;
struct ModifierData;
struct Object;
-struct ReportList;
struct Scene;
#ifdef __cplusplus
@@ -123,6 +121,13 @@ struct Mesh *BKE_mesh_new_nomain_from_template(const struct Mesh *me_src,
int tessface_len,
int loops_len,
int polys_len);
+struct Mesh *BKE_mesh_new_nomain_from_template_ex(const struct Mesh *me_src,
+ int verts_len,
+ int edges_len,
+ int tessface_len,
+ int loops_len,
+ int polys_len,
+ CustomData_MeshMasks mask);
void BKE_mesh_eval_delete(struct Mesh *me_eval);
@@ -185,7 +190,7 @@ void BKE_mesh_material_index_remove(struct Mesh *me, short index);
bool BKE_mesh_material_index_used(struct Mesh *me, short index);
void BKE_mesh_material_index_clear(struct Mesh *me);
void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len);
-void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth);
+void BKE_mesh_smooth_flag_set(struct Mesh *me, const bool use_smooth);
const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
@@ -198,18 +203,6 @@ void BKE_mesh_texspace_get_reference(
struct Mesh *me, short **r_texflag, float **r_loc, float **r_rot, float **r_size);
void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob);
-bool BKE_mesh_uv_cdlayer_rename_index(struct Mesh *me,
- const int loop_index,
- const int face_index,
- const char *new_name,
- const bool do_tessface);
-bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me,
- const char *old_name,
- const char *new_name,
- bool do_tessface);
-
-float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3];
-
void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
/* Create new mesh from the given object at its current state.
@@ -268,8 +261,14 @@ void BKE_mesh_mselect_active_set(struct Mesh *me, int index, int type);
void BKE_mesh_count_selected_items(const struct Mesh *mesh, int r_count[3]);
-void BKE_mesh_apply_vert_coords(struct Mesh *mesh, float (*vertCoords)[3]);
-void BKE_mesh_apply_vert_normals(struct Mesh *mesh, short (*vertNormals)[3]);
+float (*BKE_mesh_vert_coords_alloc(const struct Mesh *mesh, int *r_vert_len))[3];
+void BKE_mesh_vert_coords_get(const struct Mesh *mesh, float (*vert_coords)[3]);
+
+void BKE_mesh_vert_coords_apply_with_mat4(struct Mesh *mesh,
+ const float (*vert_coords)[3],
+ const float mat[4][4]);
+void BKE_mesh_vert_coords_apply(struct Mesh *mesh, const float (*vert_coords)[3]);
+void BKE_mesh_vert_normals_apply(struct Mesh *mesh, const short (*vertNormals)[3]);
/* *** mesh_evaluate.c *** */
@@ -309,11 +308,6 @@ void BKE_mesh_calc_normals_poly(struct MVert *mverts,
void BKE_mesh_calc_normals(struct Mesh *me);
void BKE_mesh_ensure_normals(struct Mesh *me);
void BKE_mesh_ensure_normals_for_display(struct Mesh *mesh);
-void BKE_mesh_calc_normals_tessface(struct MVert *mverts,
- int numVerts,
- const struct MFace *mfaces,
- int numFaces,
- float (*r_faceNors)[3]);
void BKE_mesh_calc_normals_looptri(struct MVert *mverts,
int numVerts,
const struct MLoop *mloop,
@@ -538,14 +532,14 @@ void BKE_mesh_tangent_loops_to_tessdata(struct CustomData *fdata,
unsigned int (*loopindices)[4],
const int num_faces,
const char *layer_name);
-int BKE_mesh_recalc_tessellation(struct CustomData *fdata,
- struct CustomData *ldata,
- struct CustomData *pdata,
- struct MVert *mvert,
- int totface,
- int totloop,
- int totpoly,
- const bool do_face_nor_copy);
+int BKE_mesh_tessface_calc_ex(struct CustomData *fdata,
+ struct CustomData *ldata,
+ struct CustomData *pdata,
+ struct MVert *mvert,
+ int totface,
+ int totloop,
+ int totpoly,
+ const bool do_face_nor_copy);
void BKE_mesh_recalc_looptri(const struct MLoop *mloop,
const struct MPoly *mpoly,
const struct MVert *mvert,
diff --git a/source/blender/blenkernel/BKE_mesh_iterators.h b/source/blender/blenkernel/BKE_mesh_iterators.h
index 28fd4b8bc28..b5b65944079 100644
--- a/source/blender/blenkernel/BKE_mesh_iterators.h
+++ b/source/blender/blenkernel/BKE_mesh_iterators.h
@@ -20,12 +20,6 @@
* \ingroup bke
*/
-struct MEdge;
-struct MLoop;
-struct MLoopTri;
-struct MLoopUV;
-struct MPoly;
-struct MVert;
struct Mesh;
typedef enum MeshForeachFlag {
diff --git a/source/blender/blenkernel/BKE_mesh_runtime.h b/source/blender/blenkernel/BKE_mesh_runtime.h
index 93d952bcae5..4dc9ac988e7 100644
--- a/source/blender/blenkernel/BKE_mesh_runtime.h
+++ b/source/blender/blenkernel/BKE_mesh_runtime.h
@@ -27,7 +27,6 @@
//#include "BKE_customdata.h" /* for CustomDataMask */
-struct ColorBand;
struct CustomData;
struct CustomData_MeshMasks;
struct Depsgraph;
diff --git a/source/blender/blenkernel/BKE_mesh_tangent.h b/source/blender/blenkernel/BKE_mesh_tangent.h
index bca825ce91c..4a86dfa3832 100644
--- a/source/blender/blenkernel/BKE_mesh_tangent.h
+++ b/source/blender/blenkernel/BKE_mesh_tangent.h
@@ -20,6 +20,8 @@
* \ingroup bke
*/
+struct ReportList;
+
void BKE_mesh_calc_loop_tangent_single_ex(const struct MVert *mverts,
const int numVerts,
const struct MLoop *mloops,
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 4aab2a346e7..b2bc30c107c 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -35,7 +35,6 @@ struct Mesh;
struct ModifierData;
struct Object;
struct Scene;
-struct ViewLayer;
struct bArmature;
typedef enum {
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 9b2db5acd3b..cbfc8ffc7d0 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -59,7 +59,6 @@ struct RenderData;
struct Scene;
struct SpaceNode;
struct Tex;
-struct ViewRender;
struct bContext;
struct bNode;
struct bNodeExecContext;
@@ -385,6 +384,7 @@ void ntreeUserIncrefID(struct bNodeTree *ntree);
void ntreeUserDecrefID(struct bNodeTree *ntree);
struct bNodeTree *ntreeFromID(const struct ID *id);
+struct ID *BKE_node_tree_find_owner_ID(struct Main *bmain, struct bNodeTree *ntree);
void ntreeMakeLocal(struct Main *bmain,
struct bNodeTree *ntree,
@@ -615,6 +615,7 @@ void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node);
int nodeSocketIsHidden(struct bNodeSocket *sock);
void ntreeTagUsedSockets(struct bNodeTree *ntree);
+void nodeSetSocketAvailability(struct bNodeSocket *sock, bool is_available);
/* Node Clipboard */
void BKE_node_clipboard_init(struct bNodeTree *ntree);
@@ -894,7 +895,7 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree,
#define SH_NODE_CURVE_RGB 111
#define SH_NODE_CAMERA 114
#define SH_NODE_MATH 115
-#define SH_NODE_VECT_MATH 116
+#define SH_NODE_VECTOR_MATH 116
#define SH_NODE_SQUEEZE 117
//#define SH_NODE_MATERIAL_EXT 118
#define SH_NODE_INVERT 119
@@ -977,6 +978,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree,
#define SH_NODE_BSDF_HAIR_PRINCIPLED 701
#define SH_NODE_MAP_RANGE 702
#define SH_NODE_CLAMP 703
+#define SH_NODE_TEX_WHITE_NOISE 704
+#define SH_NODE_VOLUME_INFO 705
/* custom defines options for Material node */
#define SH_NODE_MAT_DIFF 1
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index f59bf3579be..cf4bce3a209 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -43,7 +43,6 @@ struct RegionView3D;
struct RigidBodyWorld;
struct Scene;
struct ShaderFxData;
-struct SoftBody;
struct View3D;
struct ViewLayer;
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index 37667599488..ed02a34196f 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -32,7 +32,6 @@ struct Depsgraph;
struct EnumPropertyItem;
struct GridPaintMask;
struct ImagePool;
-struct MFace;
struct MLoop;
struct MLoopTri;
struct MVert;
@@ -47,7 +46,6 @@ struct Palette;
struct PaletteColor;
struct ReportList;
struct Scene;
-struct Sculpt;
struct StrokeCache;
struct SubdivCCG;
struct SubdivCCG;
@@ -259,8 +257,15 @@ typedef struct SculptSession {
struct StrokeCache *cache;
+ /* Cursor data and active vertex for tools */
int active_vertex_index;
+ float cursor_radius;
+ float cursor_location[3];
+ float cursor_normal[3];
+ float cursor_view_normal[3];
+ struct RegionView3D *rv3d;
+
union {
struct {
struct SculptVertexPaintGeomMap gmap;
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 164dbbbf482..e9b4c2b5a66 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -57,7 +57,6 @@ struct ModifierData;
struct Object;
struct RNG;
struct Scene;
-struct ViewLayer;
#define PARTICLE_COLLISION_MAX_COLLISIONS 10
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 62544efad2c..f02d41d3c65 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -28,12 +28,10 @@
struct BMLog;
struct BMesh;
-struct CCGDerivedMesh;
struct CCGElem;
struct CCGKey;
struct CustomData;
struct DMFlagMat;
-struct GPUBatch;
struct GPU_PBVH_Buffers;
struct IsectRayPrecalc;
struct MLoop;
@@ -134,8 +132,11 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
float (*origco)[3],
bool use_origco,
const float ray_start[3],
+ const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
- float *depth);
+ float *depth,
+ int *active_vertex_index,
+ float *face_normal);
bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
const float ray_start[3],
@@ -278,9 +279,9 @@ float *BKE_pbvh_node_layer_disp_get(PBVH *pbvh, PBVHNode *node);
void BKE_pbvh_node_layer_disp_free(PBVHNode *node);
/* vertex deformer */
-float (*BKE_pbvh_get_vertCos(struct PBVH *pbvh))[3];
-void BKE_pbvh_apply_vertCos(struct PBVH *pbvh, float (*vertCos)[3], const int totvert);
-bool BKE_pbvh_isDeformed(struct PBVH *pbvh);
+float (*BKE_pbvh_vert_coords_alloc(struct PBVH *pbvh))[3];
+void BKE_pbvh_vert_coords_apply(struct PBVH *pbvh, const float (*vertCos)[3], const int totvert);
+bool BKE_pbvh_is_deformed(struct PBVH *pbvh);
/* Vertex Iterator */
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index bcdf1fe48ca..7d564a232a7 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -38,8 +38,6 @@ struct TransformOrientation;
struct UnitSettings;
struct View3DCursor;
struct ViewLayer;
-struct ViewRender;
-struct WorkSpace;
typedef enum eSceneCopyMethod {
SCE_COPY_NEW = 0,
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 5d3e7ad5ec2..a2ce522a895 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -24,7 +24,6 @@
*/
struct ARegion;
-struct GPUFXSettings;
struct Header;
struct ID;
struct ListBase;
@@ -35,7 +34,6 @@ struct ScrArea;
struct ScrAreaMap;
struct ScrVert;
struct SpaceType;
-struct TransformOrientation;
struct View3D;
struct View3DShading;
struct WorkSpace;
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index a9e1dfb2392..e1bc16702d5 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -26,13 +26,11 @@
struct Depsgraph;
struct Editing;
-struct GPUFX;
struct GPUOffScreen;
struct GSet;
struct ImBuf;
struct Main;
struct Mask;
-struct RenderEngineType;
struct Scene;
struct Sequence;
struct SequenceModifierData;
diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h
index e90dbfcf68d..9fe42a214e9 100644
--- a/source/blender/blenkernel/BKE_shader_fx.h
+++ b/source/blender/blenkernel/BKE_shader_fx.h
@@ -24,22 +24,11 @@
#include "BLI_compiler_attrs.h"
#include "BKE_customdata.h"
-struct DepsNodeHandle;
-struct Depsgraph;
-struct DerivedMesh;
struct ID;
struct ListBase;
-struct Main;
-struct Mesh;
struct ModifierUpdateDepsgraphContext;
struct Object;
-struct Scene;
struct ShaderFxData;
-struct ViewLayer;
-struct bArmature;
-struct bGPDframe;
-struct bGPDlayer;
-struct bGPDstroke;
#define SHADER_FX_ACTIVE(_fx, _is_render) \
(((_fx->mode & eShaderFxMode_Realtime) && (_is_render == false)) || \
diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h
index 8993654254e..9ec75c39fcf 100644
--- a/source/blender/blenkernel/BKE_shrinkwrap.h
+++ b/source/blender/blenkernel/BKE_shrinkwrap.h
@@ -41,7 +41,6 @@
struct BVHTree;
struct MDeformVert;
-struct MVert;
struct Mesh;
struct ModifierEvalContext;
struct Object;
diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h
index d6fff528348..108e93d9caa 100644
--- a/source/blender/blenkernel/BKE_studiolight.h
+++ b/source/blender/blenkernel/BKE_studiolight.h
@@ -87,6 +87,11 @@ enum StudioLightFlag {
STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED = (1 << 11),
STUDIOLIGHT_USER_DEFINED = (1 << 12),
STUDIOLIGHT_UI_EXPANDED = (1 << 13),
+
+ STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE = (1 << 14),
+ STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE = (1 << 15),
+ /* Is set for studio lights and matcaps with specular highlight pass. */
+ STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS = (1 << 16),
};
#define STUDIOLIGHT_FLAG_ALL (STUDIOLIGHT_INTERNAL | STUDIOLIGHT_EXTERNAL_FILE)
@@ -97,6 +102,11 @@ enum StudioLightFlag {
typedef void StudioLightFreeFunction(struct StudioLight *, void *data);
+typedef struct StudioLightImage {
+ ImBuf *ibuf;
+ struct GPUTexture *gputexture;
+} StudioLightImage;
+
typedef struct StudioLight {
struct StudioLight *next, *prev;
@@ -112,6 +122,8 @@ typedef struct StudioLight {
int icon_id_matcap_flipped;
float spherical_harmonics_coefs[STUDIOLIGHT_SH_EFFECTIVE_COEFS_LEN][3];
float light_direction[3];
+ StudioLightImage matcap_diffuse;
+ StudioLightImage matcap_specular;
ImBuf *equirect_radiance_buffer;
ImBuf *equirect_irradiance_buffer;
ImBuf *radiance_cubemap_buffers[6];
diff --git a/source/blender/blenkernel/BKE_subdiv.h b/source/blender/blenkernel/BKE_subdiv.h
index dd139233ee3..700bf5139e0 100644
--- a/source/blender/blenkernel/BKE_subdiv.h
+++ b/source/blender/blenkernel/BKE_subdiv.h
@@ -29,12 +29,10 @@
struct Mesh;
struct MultiresModifierData;
-struct Object;
struct OpenSubdiv_Converter;
struct OpenSubdiv_Evaluator;
struct OpenSubdiv_TopologyRefiner;
struct Subdiv;
-struct SubdivToMeshSettings;
typedef enum eSubdivVtxBoundaryInterpolation {
/* Do not interpolate boundaries. */
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index c17db591981..39216e98e82 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -31,17 +31,13 @@ struct Brush;
struct ColorBand;
struct FreestyleLineStyle;
struct ImagePool;
-struct Light;
struct MTex;
struct Main;
-struct Material;
struct ParticleSettings;
struct PointDensity;
struct Tex;
struct TexMapping;
struct TexResult;
-struct World;
-struct bNode;
/* in ColorBand struct */
#define MAXCOLORBAND 32
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index bf417403d43..c64d684de5a 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -25,7 +25,6 @@
*/
struct Camera;
-struct Depsgraph;
struct ImBuf;
struct ListBase;
struct MovieClipUser;
diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h
index 133cf2d6cf5..ea8978b7374 100644
--- a/source/blender/blenkernel/BKE_workspace.h
+++ b/source/blender/blenkernel/BKE_workspace.h
@@ -24,9 +24,6 @@
#include "BLI_compiler_attrs.h"
struct Main;
-struct Scene;
-struct TransformOrientation;
-struct ViewLayer;
struct bScreen;
struct bToolRef;
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 6267c095618..010e162f49d 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -87,11 +87,8 @@
# define ASSERT_IS_VALID_MESH(mesh)
#endif
-static CLG_LogRef LOG = {"bke.derivedmesh"};
static ThreadRWMutex loops_cache_lock = PTHREAD_RWLOCK_INITIALIZER;
-static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid);
-
static void mesh_init_origspace(Mesh *mesh);
/* -------------------------------------------------------------------- */
@@ -516,154 +513,6 @@ void DM_ensure_looptri_data(DerivedMesh *dm)
}
}
-void DM_to_mesh(
- DerivedMesh *dm, Mesh *me, Object *ob, const CustomData_MeshMasks *mask, bool take_ownership)
-{
- /* dm might depend on me, so we need to do everything with a local copy */
- Mesh tmp = *me;
- int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
- int did_shapekeys = 0;
- eCDAllocType alloctype = CD_DUPLICATE;
-
- if (take_ownership && dm->type == DM_TYPE_CDDM && dm->needsFree) {
- bool has_any_referenced_layers = CustomData_has_referenced(&dm->vertData) ||
- CustomData_has_referenced(&dm->edgeData) ||
- CustomData_has_referenced(&dm->loopData) ||
- CustomData_has_referenced(&dm->faceData) ||
- CustomData_has_referenced(&dm->polyData);
- if (!has_any_referenced_layers) {
- alloctype = CD_ASSIGN;
- }
- }
-
- CustomData_reset(&tmp.vdata);
- CustomData_reset(&tmp.edata);
- CustomData_reset(&tmp.fdata);
- CustomData_reset(&tmp.ldata);
- CustomData_reset(&tmp.pdata);
-
- DM_ensure_normals(dm);
-
- totvert = tmp.totvert = dm->getNumVerts(dm);
- totedge = tmp.totedge = dm->getNumEdges(dm);
- totloop = tmp.totloop = dm->getNumLoops(dm);
- totpoly = tmp.totpoly = dm->getNumPolys(dm);
- tmp.totface = 0;
-
- CustomData_copy(&dm->vertData, &tmp.vdata, mask->vmask, alloctype, totvert);
- CustomData_copy(&dm->edgeData, &tmp.edata, mask->emask, alloctype, totedge);
- CustomData_copy(&dm->loopData, &tmp.ldata, mask->lmask, alloctype, totloop);
- CustomData_copy(&dm->polyData, &tmp.pdata, mask->pmask, alloctype, totpoly);
- tmp.cd_flag = dm->cd_flag;
- tmp.runtime.deformed_only = dm->deformedOnly;
-
- if (CustomData_has_layer(&dm->vertData, CD_SHAPEKEY)) {
- KeyBlock *kb;
- int uid;
-
- if (ob) {
- kb = BLI_findlink(&me->key->block, ob->shapenr - 1);
- if (kb) {
- uid = kb->uid;
- }
- else {
- CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1);
- uid = INT_MAX;
- }
- }
- else {
- /* if no object, set to INT_MAX so we don't mess up any shapekey layers */
- uid = INT_MAX;
- }
-
- shapekey_layers_to_keyblocks(dm, me, uid);
- did_shapekeys = 1;
- }
-
- /* copy texture space */
- if (ob) {
- BKE_mesh_texspace_copy_from_object(&tmp, ob);
- }
-
- /* not all DerivedMeshes store their verts/edges/faces in CustomData, so
- * we set them here in case they are missing */
- if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) {
- CustomData_add_layer(&tmp.vdata,
- CD_MVERT,
- CD_ASSIGN,
- (alloctype == CD_ASSIGN) ? dm->getVertArray(dm) : dm->dupVertArray(dm),
- totvert);
- }
- if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) {
- CustomData_add_layer(&tmp.edata,
- CD_MEDGE,
- CD_ASSIGN,
- (alloctype == CD_ASSIGN) ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm),
- totedge);
- }
- if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) {
- tmp.mloop = (alloctype == CD_ASSIGN) ? dm->getLoopArray(dm) : dm->dupLoopArray(dm);
- tmp.mpoly = (alloctype == CD_ASSIGN) ? dm->getPolyArray(dm) : dm->dupPolyArray(dm);
-
- CustomData_add_layer(&tmp.ldata, CD_MLOOP, CD_ASSIGN, tmp.mloop, tmp.totloop);
- CustomData_add_layer(&tmp.pdata, CD_MPOLY, CD_ASSIGN, tmp.mpoly, tmp.totpoly);
- }
-
- /* object had got displacement layer, should copy this layer to save sculpted data */
- /* NOTE: maybe some other layers should be copied? nazgul */
- if (CustomData_has_layer(&me->ldata, CD_MDISPS)) {
- if (totloop == me->totloop) {
- MDisps *mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
- CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop);
- }
- }
-
- /* yes, must be before _and_ after tessellate */
- BKE_mesh_update_customdata_pointers(&tmp, false);
-
- /* since 2.65 caller must do! */
- // BKE_mesh_tessface_calc(&tmp);
-
- CustomData_free(&me->vdata, me->totvert);
- CustomData_free(&me->edata, me->totedge);
- CustomData_free(&me->fdata, me->totface);
- CustomData_free(&me->ldata, me->totloop);
- CustomData_free(&me->pdata, me->totpoly);
-
- /* ok, this should now use new CD shapekey data,
- * which should be fed through the modifier
- * stack */
- if (tmp.totvert != me->totvert && !did_shapekeys && me->key) {
- CLOG_WARN(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name);
- if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) {
- id_us_min(&tmp.key->id);
- }
- tmp.key = NULL;
- }
-
- /* Clear selection history */
- MEM_SAFE_FREE(tmp.mselect);
- tmp.totselect = 0;
- BLI_assert(ELEM(tmp.bb, NULL, me->bb));
- if (me->bb) {
- MEM_freeN(me->bb);
- tmp.bb = NULL;
- }
-
- /* skip the listbase */
- MEMCPY_STRUCT_AFTER(me, &tmp, id.prev);
-
- if (take_ownership) {
- if (alloctype == CD_ASSIGN) {
- CustomData_free_typemask(&dm->vertData, dm->numVertData, ~mask->vmask);
- CustomData_free_typemask(&dm->edgeData, dm->numEdgeData, ~mask->emask);
- CustomData_free_typemask(&dm->loopData, dm->numLoopData, ~mask->lmask);
- CustomData_free_typemask(&dm->polyData, dm->numPolyData, ~mask->pmask);
- }
- dm->release(dm);
- }
-}
-
/** Utility function to convert an (evaluated) Mesh to a shape key block. */
/* Just a shallow wrapper around BKE_keyblock_convert_from_mesh,
* that ensures both evaluated mesh and original one has same number of vertices. */
@@ -819,21 +668,6 @@ void DM_interp_vert_data(DerivedMesh *source,
&source->vertData, &dest->vertData, src_indices, weights, NULL, count, dest_index);
}
-DerivedMesh *mesh_create_derived(Mesh *me, float (*vertCos)[3])
-{
- DerivedMesh *dm = CDDM_from_mesh(me);
-
- if (!dm) {
- return NULL;
- }
-
- if (vertCos) {
- CDDM_apply_vert_coords(dm, vertCos);
- }
-
- return dm;
-}
-
static float (*get_editbmesh_orco_verts(BMEditMesh *em))[3]
{
BMIter iter;
@@ -904,7 +738,7 @@ static Mesh *create_orco_mesh(Object *ob, Mesh *me, BMEditMesh *em, int layer)
orco = get_orco_coords(ob, em, layer, &free);
if (orco) {
- BKE_mesh_apply_vert_coords(mesh, orco);
+ BKE_mesh_vert_coords_apply(mesh, orco);
if (free) {
MEM_freeN(orco);
}
@@ -924,10 +758,10 @@ static void add_orco_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, Mesh *mesh_orc
free = 1;
if (mesh_orco->totvert == totvert) {
- orco = BKE_mesh_vertexCos_get(mesh_orco, NULL);
+ orco = BKE_mesh_vert_coords_alloc(mesh_orco, NULL);
}
else {
- orco = BKE_mesh_vertexCos_get(mesh, NULL);
+ orco = BKE_mesh_vert_coords_alloc(mesh, NULL);
}
}
else {
@@ -963,67 +797,6 @@ static void editmesh_update_statvis_color(const Scene *scene, Object *ob)
BKE_editmesh_statvis_calc(em, me->runtime.edit_data, &scene->toolsettings->statvis);
}
-static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid)
-{
- KeyBlock *kb;
- int i, j, tot;
-
- if (!me->key) {
- return;
- }
-
- tot = CustomData_number_of_layers(&dm->vertData, CD_SHAPEKEY);
- for (i = 0; i < tot; i++) {
- CustomDataLayer *layer =
- &dm->vertData.layers[CustomData_get_layer_index_n(&dm->vertData, CD_SHAPEKEY, i)];
- float(*cos)[3], (*kbcos)[3];
-
- for (kb = me->key->block.first; kb; kb = kb->next) {
- if (kb->uid == layer->uid) {
- break;
- }
- }
-
- if (!kb) {
- kb = BKE_keyblock_add(me->key, layer->name);
- kb->uid = layer->uid;
- }
-
- if (kb->data) {
- MEM_freeN(kb->data);
- }
-
- cos = CustomData_get_layer_n(&dm->vertData, CD_SHAPEKEY, i);
- kb->totelem = dm->numVertData;
-
- kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, 3 * sizeof(float), "kbcos DerivedMesh.c");
- if (kb->uid == actshape_uid) {
- MVert *mvert = dm->getVertArray(dm);
-
- for (j = 0; j < dm->numVertData; j++, kbcos++, mvert++) {
- copy_v3_v3(*kbcos, mvert->co);
- }
- }
- else {
- for (j = 0; j < kb->totelem; j++, cos++, kbcos++) {
- copy_v3_v3(*kbcos, *cos);
- }
- }
- }
-
- for (kb = me->key->block.first; kb; kb = kb->next) {
- if (kb->totelem != dm->numVertData) {
- if (kb->data) {
- MEM_freeN(kb->data);
- }
-
- kb->totelem = dm->numVertData;
- kb->data = MEM_calloc_arrayN(kb->totelem, 3 * sizeof(float), "kb->data derivedmesh.c");
- CLOG_ERROR(&LOG, "lost a shapekey layer: '%s'! (bmesh internal error)", kb->name);
- }
- }
-}
-
static void mesh_copy_autosmooth(Mesh *me, Mesh *me_orig)
{
if (me_orig->flag & ME_AUTOSMOOTH) {
@@ -1223,14 +996,14 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) {
if (!deformed_verts) {
- deformed_verts = BKE_mesh_vertexCos_get(mesh_input, &num_deformed_verts);
+ deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts);
}
else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
if (mesh_final == NULL) {
mesh_final = BKE_mesh_copy_for_eval(mesh_input, true);
ASSERT_IS_VALID_MESH(mesh_final);
}
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
}
modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts);
@@ -1254,7 +1027,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
mesh_deform = BKE_mesh_copy_for_eval(mesh_input, true);
if (deformed_verts) {
- BKE_mesh_apply_vert_coords(mesh_deform, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_deform, deformed_verts);
}
}
}
@@ -1337,10 +1110,10 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
/* Deforming a mesh, read the vertex locations
* out of the mesh and deform them. Once done with this
* run of deformers verts will be written back. */
- deformed_verts = BKE_mesh_vertexCos_get(mesh_final, &num_deformed_verts);
+ deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts);
}
else {
- deformed_verts = BKE_mesh_vertexCos_get(mesh_input, &num_deformed_verts);
+ deformed_verts = BKE_mesh_vert_coords_alloc(mesh_input, &num_deformed_verts);
}
}
/* if this is not the last modifier in the stack then recalculate the normals
@@ -1348,7 +1121,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
/* XXX, this covers bug #23673, but we may need normal calc for other types */
if (mesh_final) {
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
}
}
@@ -1367,7 +1140,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
/* apply vertex coordinates or build a Mesh as necessary */
if (mesh_final) {
if (deformed_verts) {
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
}
}
else {
@@ -1375,7 +1148,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
ASSERT_IS_VALID_MESH(mesh_final);
if (deformed_verts) {
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
}
/* Initialize original indices the first time we evaluate a
@@ -1554,7 +1327,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
}
}
if (deformed_verts) {
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
MEM_freeN(deformed_verts);
deformed_verts = NULL;
}
@@ -1614,14 +1387,14 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph,
}
}
-float (*editbmesh_get_vertex_cos(BMEditMesh *em, int *r_numVerts))[3]
+float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3]
{
BMIter iter;
BMVert *eve;
float(*cos)[3];
int i;
- *r_numVerts = em->bm->totvert;
+ *r_vert_len = em->bm->totvert;
cos = MEM_malloc_arrayN(em->bm->totvert, 3 * sizeof(float), "vertexcos");
@@ -1793,10 +1566,10 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
/* Deforming a derived mesh, read the vertex locations
* out of the mesh and deform them. Once done with this
* run of deformers verts will be written back. */
- deformed_verts = BKE_mesh_vertexCos_get(mesh_final, &num_deformed_verts);
+ deformed_verts = BKE_mesh_vert_coords_alloc(mesh_final, &num_deformed_verts);
}
else {
- deformed_verts = editbmesh_get_vertex_cos(em_input, &num_deformed_verts);
+ deformed_verts = editbmesh_vert_coords_alloc(em_input, &num_deformed_verts);
}
}
else if (isPrevDeform && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
@@ -1806,7 +1579,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
mesh_copy_autosmooth(mesh_final, mesh_input);
}
BLI_assert(deformed_verts != NULL);
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
}
if (mti->deformVertsEM) {
@@ -1826,7 +1599,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
BKE_id_free(NULL, mesh_final);
}
mesh_final = mesh_tmp;
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
}
else if (mesh_final == mesh_cage) {
/* 'me' may be changed by this modifier, so we need to copy it. */
@@ -1840,7 +1613,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
mesh_copy_autosmooth(mesh_final, mesh_input);
if (deformed_verts) {
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
}
}
@@ -1910,7 +1683,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
if (r_cage && i == cageIndex) {
if (mesh_final && deformed_verts) {
mesh_cage = BKE_mesh_copy_for_eval(mesh_final, false);
- BKE_mesh_apply_vert_coords(mesh_cage, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_cage, deformed_verts);
}
else if (mesh_final) {
mesh_cage = mesh_final;
@@ -1942,7 +1715,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
BKE_id_free(NULL, mesh_final);
}
mesh_final = mesh_tmp;
- BKE_mesh_apply_vert_coords(mesh_final, deformed_verts);
+ BKE_mesh_vert_coords_apply(mesh_final, deformed_verts);
}
}
else if (!deformed_verts && mesh_cage) {
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 1a34c5376f6..ab8ea37377d 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -648,7 +648,7 @@ char *BKE_animdata_driver_path_hack(bContext *C,
PropertyRNA *prop,
char *base_path)
{
- ID *id = (ID *)ptr->id.data;
+ ID *id = ptr->owner_id;
ScrArea *sa = CTX_wm_area(C);
/* get standard path which may be extended */
@@ -1656,14 +1656,14 @@ static bool animsys_store_rna_setting(PointerRNA *ptr,
if (path) {
/* get property to write to */
if (RNA_path_resolve_property(ptr, path, &r_result->ptr, &r_result->prop)) {
- if ((ptr->id.data == NULL) || RNA_property_animateable(&r_result->ptr, r_result->prop)) {
+ if ((ptr->owner_id == NULL) || RNA_property_animateable(&r_result->ptr, r_result->prop)) {
int array_len = RNA_property_array_length(&r_result->ptr, r_result->prop);
if (array_len && array_index >= array_len) {
if (G.debug & G_DEBUG) {
CLOG_WARN(&LOG,
"Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d",
- (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>",
+ (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>",
path,
array_index,
array_len - 1);
@@ -1682,7 +1682,7 @@ static bool animsys_store_rna_setting(PointerRNA *ptr,
if (G.debug & G_DEBUG) {
CLOG_WARN(&LOG,
"Animato: Invalid path. ID = '%s', '%s[%d]'",
- (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>",
+ (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>",
path,
array_index);
}
@@ -1703,7 +1703,7 @@ static bool animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value)
float orig_value;
/* caller must ensure this is animatable */
- BLI_assert(RNA_property_animateable(ptr, prop) || ptr->id.data == NULL);
+ BLI_assert(RNA_property_animateable(ptr, prop) || ptr->owner_id == NULL);
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN: {
@@ -1765,7 +1765,7 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val
int array_index = anim_rna->prop_index;
/* caller must ensure this is animatable */
- BLI_assert(RNA_property_animateable(ptr, prop) || ptr->id.data == NULL);
+ BLI_assert(RNA_property_animateable(ptr, prop) || ptr->owner_id == NULL);
/* Check whether value is new. Otherwise we skip all the updates. */
float old_value;
@@ -1844,7 +1844,7 @@ static bool animsys_construct_orig_pointer_rna(const PointerRNA *ptr, PointerRNA
* not a valid pointer, but there are exceptions in various places of this file which handles
* such pointers.
* We do special trickery here as well, to quickly go from evaluated to original NlaStrip. */
- if (ptr->id.data == NULL) {
+ if (ptr->owner_id == NULL) {
if (ptr->type != &RNA_NlaStrip) {
return false;
}
@@ -1855,8 +1855,8 @@ static bool animsys_construct_orig_pointer_rna(const PointerRNA *ptr, PointerRNA
ptr_orig->data = strip->orig_strip;
}
else {
- ptr_orig->id.data = ((ID *)ptr_orig->id.data)->orig_id;
- ptr_orig->data = ptr_orig->id.data;
+ ptr_orig->owner_id = ptr_orig->owner_id->orig_id;
+ ptr_orig->data = ptr_orig->owner_id;
}
return true;
}
@@ -2003,7 +2003,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup *
return;
}
- action_idcode_patch_check(ptr->id.data, act);
+ action_idcode_patch_check(ptr->owner_id, act);
/* if group is muted, don't evaluated any of the F-Curve */
if (agrp->flag & AGRP_MUTED) {
@@ -2034,7 +2034,7 @@ static void animsys_evaluate_action_ex(PointerRNA *ptr,
return;
}
- action_idcode_patch_check(ptr->id.data, act);
+ action_idcode_patch_check(ptr->owner_id, act);
/* calculate then execute each curve */
animsys_evaluate_fcurves(ptr, &act->curves, ctime, flush_to_original);
@@ -2643,7 +2643,7 @@ static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, NlaEvalData *nlaeval,
if (G.debug & G_DEBUG) {
CLOG_WARN(&LOG,
"Animato: Invalid path. ID = '%s', '%s'",
- (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>",
+ (ptr->owner_id) ? (ptr->owner_id->name + 2) : "<No ID>",
path);
}
@@ -2651,7 +2651,7 @@ static NlaEvalChannel *nlaevalchan_verify(PointerRNA *ptr, NlaEvalData *nlaeval,
}
/* Check that the property can be animated. */
- if (ptr->id.data != NULL && !RNA_property_animateable(&key.ptr, key.prop)) {
+ if (ptr->owner_id != NULL && !RNA_property_animateable(&key.ptr, key.prop)) {
return NULL;
}
@@ -2884,7 +2884,7 @@ static bool nlaeval_blend_value(NlaBlendData *blend,
if (index < 0) {
if (G.debug & G_DEBUG) {
- ID *id = nec->key.ptr.id.data;
+ ID *id = nec->key.ptr.owner_id;
CLOG_WARN(&LOG,
"Animato: Invalid array index. ID = '%s', '%s[%d]', array length is %d",
id ? (id->name + 2) : "<No ID>",
@@ -3081,7 +3081,7 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
return;
}
- action_idcode_patch_check(ptr->id.data, strip->act);
+ action_idcode_patch_check(ptr->owner_id, strip->act);
/* join this strip's modifiers to the parent's modifiers (own modifiers first) */
nlaeval_fmodifiers_join_stacks(&tmp_modifiers, &strip->modifiers, modifiers);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index ea927ca9333..168422a4454 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -268,6 +268,90 @@ void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature
}
}
+/** Helper for #ED_armature_transform */
+static void armature_transform_recurse(ListBase *bonebase,
+ const float mat[4][4],
+ const bool do_props,
+ /* Cached from 'mat'. */
+ const float mat3[3][3],
+ const float scale,
+ /* Child bones. */
+ const Bone *bone_parent,
+ const float arm_mat_parent_inv[4][4])
+{
+ for (Bone *bone = bonebase->first; bone; bone = bone->next) {
+
+ /* Transform the bone's roll. */
+ if (bone_parent == NULL) {
+
+ float roll_mat[3][3];
+ {
+ float delta[3];
+ sub_v3_v3v3(delta, bone->tail, bone->head);
+ vec_roll_to_mat3(delta, bone->roll, roll_mat);
+ }
+
+ /* Transform the roll matrix. */
+ mul_m3_m3m3(roll_mat, mat3, roll_mat);
+
+ /* Apply the transformed roll back. */
+ mat3_to_vec_roll(roll_mat, NULL, &bone->roll);
+ }
+
+ mul_m4_v3(mat, bone->arm_head);
+ mul_m4_v3(mat, bone->arm_tail);
+
+ /* Get the new head and tail */
+ if (bone_parent) {
+ sub_v3_v3v3(bone->head, bone->arm_head, bone_parent->arm_tail);
+ sub_v3_v3v3(bone->tail, bone->arm_tail, bone_parent->arm_tail);
+
+ mul_mat3_m4_v3(arm_mat_parent_inv, bone->head);
+ mul_mat3_m4_v3(arm_mat_parent_inv, bone->tail);
+ }
+ else {
+ copy_v3_v3(bone->head, bone->arm_head);
+ copy_v3_v3(bone->tail, bone->arm_tail);
+ }
+
+ BKE_armature_where_is_bone(bone, bone_parent, false);
+
+ {
+ float arm_mat3[3][3];
+ copy_m3_m4(arm_mat3, bone->arm_mat);
+ mat3_to_vec_roll(arm_mat3, NULL, &bone->arm_roll);
+ }
+
+ if (do_props) {
+ bone->rad_head *= scale;
+ bone->rad_tail *= scale;
+ bone->dist *= scale;
+
+ /* we could be smarter and scale by the matrix along the x & z axis */
+ bone->xwidth *= scale;
+ bone->zwidth *= scale;
+ }
+
+ if (!BLI_listbase_is_empty(&bone->childbase)) {
+ float arm_mat_inv[4][4];
+ invert_m4_m4(arm_mat_inv, bone->arm_mat);
+ armature_transform_recurse(&bone->childbase, mat, do_props, mat3, scale, bone, arm_mat_inv);
+ }
+ }
+}
+
+void BKE_armature_transform(bArmature *arm, const float mat[4][4], const bool do_props)
+{
+ /* Store the scale of the matrix here to use on envelopes. */
+ float scale = mat4_to_scale(mat);
+ float mat3[3][3];
+
+ copy_m3_m4(mat3, mat);
+ normalize_m3(mat3);
+
+ armature_transform_recurse(&arm->bonebase, mat, do_props, mat3, scale, NULL, NULL);
+}
+
static Bone *get_named_bone_bonechildren(ListBase *lb, const char *name)
{
Bone *curBone, *rbone;
@@ -2285,7 +2369,7 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3])
/* recursive part, calculates restposition of entire tree of children */
/* used by exiting editmode too */
-void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone, const bool use_recursion)
+void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, const bool use_recursion)
{
float vec[3];
@@ -2301,13 +2385,13 @@ void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone, const bool use_recur
bone->segments = 1;
}
- if (prevbone) {
+ if (bone_parent) {
float offs_bone[4][4];
/* yoffs(b-1) + root(b) + bonemat(b) */
BKE_bone_offset_matrix_get(bone, offs_bone);
/* Compose the matrix for this bone */
- mul_m4_m4m4(bone->arm_mat, prevbone->arm_mat, offs_bone);
+ mul_m4_m4m4(bone->arm_mat, bone_parent->arm_mat, offs_bone);
}
else {
copy_m4_m3(bone->arm_mat, bone->bone_mat);
@@ -2316,9 +2400,9 @@ void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone, const bool use_recur
/* and the kiddies */
if (use_recursion) {
- prevbone = bone;
+ bone_parent = bone;
for (bone = bone->childbase.first; bone; bone = bone->next) {
- BKE_armature_where_is_bone(bone, prevbone, use_recursion);
+ BKE_armature_where_is_bone(bone, bone_parent, use_recursion);
}
}
}
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index bf7d81e5d63..00975976130 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -887,9 +887,10 @@ void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph, Object *object,
}
BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
+ BLI_assert(pchan != NULL);
DEG_debug_print_eval_subdata(
depsgraph, __func__, object->id.name, object, "pchan", pchan->name, pchan);
- /* TODO(sergey): Use indexec lookup, once it's guaranteed to be kept
+ /* TODO(sergey): Use indexed lookup, once it's guaranteed to be kept
* around for the time while proxies are evaluating.
*/
#if 0
@@ -897,8 +898,13 @@ void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph, Object *object,
#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);
+ if (pchan_from == NULL) {
+ printf(
+ "WARNING: Could not find bone %s in linked ID anymore... "
+ "You should delete and re-generate your proxy.\n",
+ pchan->name);
+ return;
+ }
BKE_pose_copyesult_pchan_result(pchan, pchan_from);
copy_dq_dq(&pchan->runtime.deform_dual_quat, &pchan_from->runtime.deform_dual_quat);
BKE_pchan_bbone_segments_cache_copy(pchan, pchan_from);
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index b2d3ccfebc3..83e4a582ff1 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -72,6 +72,7 @@ static void brush_defaults(Brush *brush)
brush->autosmooth_factor = 0.0f;
brush->topology_rake_factor = 0.0f;
brush->crease_pinch_factor = 0.5f;
+ brush->normal_radius_factor = 0.5f;
brush->sculpt_plane = SCULPT_DISP_DIR_AREA;
/* How far above or below the plane that is found by averaging the faces. */
brush->plane_offset = 0.0f;
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 8c125d1609b..85a12027bf2 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -425,11 +425,11 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(float epsilon,
int tree_type,
int axis,
BMEditMesh *em,
- const int verts_num,
const BLI_bitmap *verts_mask,
int verts_num_active)
{
BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+ const int verts_num = em->bm->totvert;
if (verts_mask) {
BLI_assert(IN_RANGE_INCL(verts_num_active, 0, verts_num));
}
@@ -516,53 +516,53 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
int verts_num_active,
float epsilon,
int tree_type,
- int axis)
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache)
{
- BVHTree *tree = bvhtree_from_editmesh_verts_create_tree(
- epsilon, tree_type, axis, em, em->bm->totvert, verts_mask, verts_num_active);
-
- if (tree) {
- memset(data, 0, sizeof(*data));
- data->tree = tree;
- data->em = em;
- data->nearest_callback = NULL;
- data->raycast_callback = editmesh_verts_spherecast;
- }
-
- return tree;
-}
+ BVHTree *tree = NULL;
-BVHTree *bvhtree_from_editmesh_verts(BVHTreeFromEditMesh *data,
- BMEditMesh *em,
- float epsilon,
- int tree_type,
- int axis,
- BVHCache **bvh_cache)
-{
if (bvh_cache) {
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- data->cached = bvhcache_find(*bvh_cache, BVHTREE_FROM_EM_VERTS, &data->tree);
+ data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &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);
+ data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree);
if (data->cached == false) {
- data->tree = bvhtree_from_editmesh_verts_ex(data, em, NULL, -1, epsilon, tree_type, axis);
+ tree = bvhtree_from_editmesh_verts_create_tree(
+ epsilon, tree_type, axis, em, verts_mask, verts_num_active);
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(bvh_cache, data->tree, BVHTREE_FROM_EM_VERTS);
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
data->cached = true;
}
BLI_rw_mutex_unlock(&cache_rwlock);
}
}
else {
- data->tree = bvhtree_from_editmesh_verts_ex(data, em, NULL, -1, epsilon, tree_type, axis);
+ tree = bvhtree_from_editmesh_verts_create_tree(
+ epsilon, tree_type, axis, em, verts_mask, verts_num_active);
}
- return data->tree;
+ if (tree) {
+ memset(data, 0, sizeof(*data));
+ data->tree = tree;
+ data->em = em;
+ data->nearest_callback = NULL;
+ data->raycast_callback = editmesh_verts_spherecast;
+ data->cached = bvh_cache != NULL;
+ }
+
+ return tree;
+}
+
+BVHTree *bvhtree_from_editmesh_verts(
+ BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
+{
+ return bvhtree_from_editmesh_verts_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL);
}
/**
@@ -580,13 +580,40 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
int verts_num_active,
float epsilon,
int tree_type,
- int axis)
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache)
{
- BVHTree *tree = bvhtree_from_mesh_verts_create_tree(
- epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active);
+ bool in_cache = false;
+ BVHTree *tree = NULL;
+ if (bvh_cache) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
+ in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ if (in_cache == false) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+ in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
+ if (in_cache) {
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ }
+ }
+
+ if (in_cache == false) {
+ tree = bvhtree_from_mesh_verts_create_tree(
+ epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active);
+
+ if (bvh_cache) {
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ in_cache = true;
+ }
+ }
/* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_verts_setup_data(data, tree, false, vert, vert_allocated);
+ bvhtree_from_mesh_verts_setup_data(data, tree, in_cache, vert, vert_allocated);
return tree;
}
@@ -601,11 +628,12 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(float epsilon,
int tree_type,
int axis,
BMEditMesh *em,
- const int edges_num,
const BLI_bitmap *edges_mask,
int edges_num_active)
{
BM_mesh_elem_table_ensure(em->bm, BM_EDGE);
+ const int edges_num = em->bm->totedge;
+
if (edges_mask) {
BLI_assert(IN_RANGE_INCL(edges_num_active, 0, edges_num));
}
@@ -705,55 +733,53 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
int edges_num_active,
float epsilon,
int tree_type,
- int axis)
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache)
{
- int edge_num = em->bm->totedge;
-
- BVHTree *tree = bvhtree_from_editmesh_edges_create_tree(
- epsilon, tree_type, axis, em, edge_num, edges_mask, edges_num_active);
-
- if (tree) {
- memset(data, 0, sizeof(*data));
- data->tree = tree;
- data->em = em;
- data->nearest_callback = NULL; /* TODO */
- data->raycast_callback = NULL; /* TODO */
- }
-
- return tree;
-}
+ BVHTree *tree = NULL;
-BVHTree *bvhtree_from_editmesh_edges(BVHTreeFromEditMesh *data,
- BMEditMesh *em,
- float epsilon,
- int tree_type,
- int axis,
- BVHCache **bvh_cache)
-{
if (bvh_cache) {
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- data->cached = bvhcache_find(*bvh_cache, BVHTREE_FROM_EM_EDGES, &data->tree);
+ data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &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);
+ data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree);
if (data->cached == false) {
- data->tree = bvhtree_from_editmesh_edges_ex(data, em, NULL, -1, epsilon, tree_type, axis);
+ tree = bvhtree_from_editmesh_edges_create_tree(
+ epsilon, tree_type, axis, em, edges_mask, edges_num_active);
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(bvh_cache, data->tree, BVHTREE_FROM_EM_EDGES);
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
data->cached = true;
}
BLI_rw_mutex_unlock(&cache_rwlock);
}
}
else {
- data->tree = bvhtree_from_editmesh_edges_ex(data, em, NULL, -1, epsilon, tree_type, axis);
+ tree = bvhtree_from_editmesh_edges_create_tree(
+ epsilon, tree_type, axis, em, edges_mask, edges_num_active);
}
- return data->tree;
+ if (tree) {
+ memset(data, 0, sizeof(*data));
+ data->tree = tree;
+ data->em = em;
+ data->nearest_callback = NULL; /* TODO */
+ data->raycast_callback = NULL; /* TODO */
+ data->cached = bvh_cache != NULL;
+ }
+
+ return tree;
+}
+
+BVHTree *bvhtree_from_editmesh_edges(
+ BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
+{
+ return bvhtree_from_editmesh_edges_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL);
}
/**
@@ -774,14 +800,41 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
int edges_num_active,
float epsilon,
int tree_type,
- int axis)
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache)
{
- BVHTree *tree = bvhtree_from_mesh_edges_create_tree(
- vert, edge, edges_num, edges_mask, edges_num_active, epsilon, tree_type, axis);
+ bool in_cache = false;
+ BVHTree *tree = NULL;
+ if (bvh_cache) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
+ in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ if (in_cache == false) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+ in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
+ if (in_cache) {
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ }
+ }
+
+ if (in_cache == false) {
+ tree = bvhtree_from_mesh_edges_create_tree(
+ vert, edge, edges_num, edges_mask, edges_num_active, epsilon, tree_type, axis);
+
+ if (bvh_cache) {
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ in_cache = true;
+ }
+ }
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_edges_setup_data(
- data, tree, false, vert, vert_allocated, edge, edge_allocated);
+ data, tree, in_cache, vert, vert_allocated, edge, edge_allocated);
return tree;
}
@@ -882,14 +935,41 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data,
int faces_num_active,
float epsilon,
int tree_type,
- int axis)
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache)
{
- BVHTree *tree = bvhtree_from_mesh_faces_create_tree(
- epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active);
+ bool in_cache = false;
+ BVHTree *tree = NULL;
+ if (bvh_cache) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
+ in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ if (in_cache == false) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+ in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
+ if (in_cache) {
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ }
+ }
+
+ if (in_cache == false) {
+ tree = bvhtree_from_mesh_faces_create_tree(
+ epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active);
+
+ if (bvh_cache) {
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ in_cache = true;
+ }
+ }
/* Setup BVHTreeFromMesh */
bvhtree_from_mesh_faces_setup_data(
- data, tree, false, vert, vert_allocated, face, face_allocated);
+ data, tree, in_cache, vert, vert_allocated, face, face_allocated);
return tree;
}
@@ -904,12 +984,11 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon,
int tree_type,
int axis,
BMEditMesh *em,
- const int looptri_num,
const BLI_bitmap *looptri_mask,
int looptri_num_active)
{
BVHTree *tree = NULL;
- int i;
+ const int looptri_num = em->tottri;
if (looptri_num) {
if (looptri_mask) {
@@ -923,26 +1002,24 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(float epsilon,
/* printf("%s: building BVH, total=%d\n", __func__, numFaces); */
tree = BLI_bvhtree_new(looptri_num_active, epsilon, tree_type, axis);
if (tree) {
- if (em) {
- const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
-
- /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
- * and/or selected. Even if the faces themselves are not selected for the snapped
- * transform, having a vertex selected means the face (and thus it's tessellated
- * triangles) will be moving and will not be a good snap targets. */
- for (i = 0; i < looptri_num; i++) {
- const BMLoop **ltri = looptris[i];
- bool insert = looptri_mask ? BLI_BITMAP_TEST_BOOL(looptri_mask, i) : true;
-
- if (insert) {
- /* No reason found to block hit-testing the triangle for snap, so insert it now.*/
- float co[3][3];
- copy_v3_v3(co[0], ltri[0]->v->co);
- copy_v3_v3(co[1], ltri[1]->v->co);
- copy_v3_v3(co[2], ltri[2]->v->co);
-
- BLI_bvhtree_insert(tree, i, co[0], 3);
- }
+ const struct BMLoop *(*looptris)[3] = (void *)em->looptris;
+
+ /* Insert BMesh-tessellation triangles into the bvh tree, unless they are hidden
+ * and/or selected. Even if the faces themselves are not selected for the snapped
+ * transform, having a vertex selected means the face (and thus it's tessellated
+ * triangles) will be moving and will not be a good snap targets. */
+ for (int i = 0; i < looptri_num; i++) {
+ const BMLoop **ltri = looptris[i];
+ bool insert = looptri_mask ? BLI_BITMAP_TEST_BOOL(looptri_mask, i) : true;
+
+ if (insert) {
+ /* No reason found to block hit-testing the triangle for snap, so insert it now.*/
+ float co[3][3];
+ copy_v3_v3(co[0], ltri[0]->v->co);
+ copy_v3_v3(co[1], ltri[1]->v->co);
+ copy_v3_v3(co[2], ltri[2]->v->co);
+
+ BLI_bvhtree_insert(tree, i, co[0], 3);
}
}
BLI_assert(BLI_bvhtree_get_len(tree) == looptri_num_active);
@@ -1035,33 +1112,34 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
float epsilon,
int tree_type,
int axis,
- BVHCache **bvhCache)
+ const int bvh_cache_type,
+ BVHCache **bvh_cache)
{
/* BMESH specific check that we have tessfaces,
* we _could_ tessellate here but rather not - campbell */
BVHTree *tree = NULL;
- if (bvhCache) {
+ if (bvh_cache) {
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- bool in_cache = bvhcache_find(*bvhCache, BVHTREE_FROM_EM_LOOPTRI, &tree);
+ bool in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
BLI_rw_mutex_unlock(&cache_rwlock);
if (in_cache == false) {
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvhCache, BVHTREE_FROM_EM_LOOPTRI, &tree);
+ in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
if (in_cache == false) {
tree = bvhtree_from_editmesh_looptri_create_tree(
- epsilon, tree_type, axis, em, em->tottri, looptri_mask, looptri_num_active);
+ epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(bvhCache, tree, BVHTREE_FROM_EM_LOOPTRI);
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
}
BLI_rw_mutex_unlock(&cache_rwlock);
}
}
else {
tree = bvhtree_from_editmesh_looptri_create_tree(
- epsilon, tree_type, axis, em, em->tottri, looptri_mask, looptri_num_active);
+ epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
}
if (tree) {
@@ -1069,19 +1147,15 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
data->nearest_callback = editmesh_looptri_nearest_point;
data->raycast_callback = editmesh_looptri_spherecast;
data->em = em;
- data->cached = bvhCache != NULL;
+ data->cached = bvh_cache != NULL;
}
return tree;
}
-BVHTree *bvhtree_from_editmesh_looptri(BVHTreeFromEditMesh *data,
- BMEditMesh *em,
- float epsilon,
- int tree_type,
- int axis,
- BVHCache **bvhCache)
+BVHTree *bvhtree_from_editmesh_looptri(
+ BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
{
- return bvhtree_from_editmesh_looptri_ex(data, em, NULL, -1, epsilon, tree_type, axis, bvhCache);
+ return bvhtree_from_editmesh_looptri_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL);
}
/**
@@ -1101,21 +1175,54 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
int looptri_num_active,
float epsilon,
int tree_type,
- int axis)
+ int axis,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache)
{
- BVHTree *tree = bvhtree_from_mesh_looptri_create_tree(epsilon,
- tree_type,
- axis,
- vert,
- mloop,
- looptri,
- looptri_num,
- looptri_mask,
- looptri_num_active);
+ bool in_cache = false;
+ BVHTree *tree = NULL;
+ if (bvh_cache) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
+ in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ if (in_cache == false) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
+ in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
+ if (in_cache) {
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ }
+ }
+
+ if (in_cache == false) {
+ /* Setup BVHTreeFromMesh */
+ tree = bvhtree_from_mesh_looptri_create_tree(epsilon,
+ tree_type,
+ axis,
+ vert,
+ mloop,
+ looptri,
+ looptri_num,
+ looptri_mask,
+ looptri_num_active);
+
+ if (bvh_cache) {
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+ in_cache = true;
+ }
+ }
/* Setup BVHTreeFromMesh */
- bvhtree_from_mesh_looptri_setup_data(
- data, tree, false, vert, vert_allocated, mloop, loop_allocated, looptri, looptri_allocated);
+ bvhtree_from_mesh_looptri_setup_data(data,
+ tree,
+ in_cache,
+ vert,
+ vert_allocated,
+ mloop,
+ loop_allocated,
+ looptri,
+ looptri_allocated);
return tree;
}
@@ -1204,164 +1311,154 @@ static BLI_bitmap *looptri_no_hidden_map_get(const MPoly *mpoly,
*/
BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
struct Mesh *mesh,
- const int type,
+ const int bvh_cache_type,
const int tree_type)
{
- struct BVHTreeFromMesh data_cp = {0};
+ BVHTree *tree = NULL;
+ BVHCache **bvh_cache = &mesh->runtime.bvh_cache;
BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- data_cp.cached = bvhcache_find(mesh->runtime.bvh_cache, type, &data_cp.tree);
+ bool is_cached = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
BLI_rw_mutex_unlock(&cache_rwlock);
- if (data_cp.cached && data_cp.tree == NULL) {
+ if (is_cached && tree == NULL) {
memset(data, 0, sizeof(*data));
- return data_cp.tree;
+ return tree;
}
- switch (type) {
+ switch (bvh_cache_type) {
case BVHTREE_FROM_VERTS:
case BVHTREE_FROM_LOOSEVERTS:
- data_cp.raycast_callback = mesh_verts_spherecast;
-
- data_cp.vert = mesh->mvert;
+ if (is_cached == false) {
+ BLI_bitmap *loose_verts_mask = NULL;
+ int loose_vert_len = -1;
+ int verts_len = mesh->totvert;
+
+ if (bvh_cache_type == BVHTREE_FROM_LOOSEVERTS) {
+ loose_verts_mask = loose_verts_map_get(
+ mesh->medge, mesh->totedge, mesh->mvert, verts_len, &loose_vert_len);
+ }
- if (data_cp.cached == false) {
/* TODO: a global mutex lock held during the expensive operation of
* building the BVH tree is really bad for performance. */
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- data_cp.cached = bvhcache_find(mesh->runtime.bvh_cache, type, &data_cp.tree);
-
- if (data_cp.cached == false) {
- BLI_bitmap *loose_verts_mask = NULL;
- int loose_vert_len = -1;
- int verts_len = mesh->totvert;
-
- if (type == BVHTREE_FROM_LOOSEVERTS) {
- loose_verts_mask = loose_verts_map_get(
- mesh->medge, mesh->totedge, data_cp.vert, verts_len, &loose_vert_len);
- }
-
- data_cp.tree = bvhtree_from_mesh_verts_create_tree(
- 0.0, tree_type, 6, data_cp.vert, verts_len, loose_verts_mask, loose_vert_len);
-
- if (loose_verts_mask != NULL) {
- MEM_freeN(loose_verts_mask);
- }
-
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(&mesh->runtime.bvh_cache, data_cp.tree, type);
+ tree = bvhtree_from_mesh_verts_ex(data,
+ mesh->mvert,
+ verts_len,
+ false,
+ loose_verts_mask,
+ loose_vert_len,
+ 0.0f,
+ tree_type,
+ 6,
+ bvh_cache_type,
+ bvh_cache);
+
+ if (loose_verts_mask != NULL) {
+ MEM_freeN(loose_verts_mask);
}
- BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ else {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_verts_setup_data(data, tree, true, mesh->mvert, false);
}
break;
case BVHTREE_FROM_EDGES:
case BVHTREE_FROM_LOOSEEDGES:
- data_cp.nearest_callback = mesh_edges_nearest_point;
- data_cp.raycast_callback = mesh_edges_spherecast;
-
- data_cp.vert = mesh->mvert;
- data_cp.edge = mesh->medge;
-
- if (data_cp.cached == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- data_cp.cached = bvhcache_find(mesh->runtime.bvh_cache, type, &data_cp.tree);
- if (data_cp.cached == false) {
- BLI_bitmap *loose_edges_mask = NULL;
- int loose_edges_len = -1;
- int edges_len = mesh->totedge;
-
- if (type == BVHTREE_FROM_LOOSEEDGES) {
- loose_edges_mask = loose_edges_map_get(data_cp.edge, edges_len, &loose_edges_len);
- }
+ if (is_cached == false) {
+ BLI_bitmap *loose_edges_mask = NULL;
+ int loose_edges_len = -1;
+ int edges_len = mesh->totedge;
- data_cp.tree = bvhtree_from_mesh_edges_create_tree(data_cp.vert,
- data_cp.edge,
- edges_len,
- loose_edges_mask,
- loose_edges_len,
- 0.0,
- tree_type,
- 6);
-
- if (loose_edges_mask != NULL) {
- MEM_freeN(loose_edges_mask);
- }
+ if (bvh_cache_type == BVHTREE_FROM_LOOSEEDGES) {
+ loose_edges_mask = loose_edges_map_get(mesh->medge, edges_len, &loose_edges_len);
+ }
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(&mesh->runtime.bvh_cache, data_cp.tree, type);
+ tree = bvhtree_from_mesh_edges_ex(data,
+ mesh->mvert,
+ false,
+ mesh->medge,
+ edges_len,
+ false,
+ loose_edges_mask,
+ loose_edges_len,
+ 0.0,
+ tree_type,
+ 6,
+ bvh_cache_type,
+ bvh_cache);
+
+ if (loose_edges_mask != NULL) {
+ MEM_freeN(loose_edges_mask);
}
- BLI_rw_mutex_unlock(&cache_rwlock);
+ }
+ else {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_edges_setup_data(
+ data, tree, false, mesh->mvert, false, mesh->medge, false);
}
break;
case BVHTREE_FROM_FACES:
- data_cp.nearest_callback = mesh_faces_nearest_point;
- data_cp.raycast_callback = mesh_faces_spherecast;
-
- data_cp.vert = mesh->mvert;
- data_cp.face = mesh->mface;
-
- if (data_cp.cached == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- data_cp.cached = bvhcache_find(mesh->runtime.bvh_cache, BVHTREE_FROM_FACES, &data_cp.tree);
- if (data_cp.cached == false) {
- int num_faces = mesh->totface;
- BLI_assert(!(num_faces == 0 && mesh->totpoly != 0));
-
- data_cp.tree = bvhtree_from_mesh_faces_create_tree(
- 0.0, tree_type, 6, data_cp.vert, data_cp.face, num_faces, NULL, -1);
-
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(&mesh->runtime.bvh_cache, data_cp.tree, BVHTREE_FROM_FACES);
- }
- BLI_rw_mutex_unlock(&cache_rwlock);
+ if (is_cached == false) {
+ int num_faces = mesh->totface;
+ BLI_assert(!(num_faces == 0 && mesh->totpoly != 0));
+
+ tree = bvhtree_from_mesh_faces_ex(data,
+ mesh->mvert,
+ false,
+ mesh->mface,
+ num_faces,
+ false,
+ NULL,
+ -1,
+ 0.0,
+ tree_type,
+ 6,
+ bvh_cache_type,
+ bvh_cache);
+ }
+ else {
+ /* Setup BVHTreeFromMesh */
+ bvhtree_from_mesh_faces_setup_data(
+ data, tree, true, mesh->mvert, false, mesh->mface, false);
}
break;
case BVHTREE_FROM_LOOPTRI:
case BVHTREE_FROM_LOOPTRI_NO_HIDDEN:
- data_cp.nearest_callback = mesh_looptri_nearest_point;
- data_cp.raycast_callback = mesh_looptri_spherecast;
-
- data_cp.vert = mesh->mvert;
- data_cp.loop = mesh->mloop;
-
- /* TODO: store looptris somewhere? */
- data_cp.looptri = BKE_mesh_runtime_looptri_ensure(mesh);
-
- if (data_cp.cached == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- data_cp.cached = bvhcache_find(
- mesh->runtime.bvh_cache, BVHTREE_FROM_LOOPTRI, &data_cp.tree);
- if (data_cp.cached == false) {
- BLI_bitmap *looptri_mask = NULL;
- int looptri_mask_active_len = -1;
- int looptri_len = BKE_mesh_runtime_looptri_len(mesh);
-
- if (type == BVHTREE_FROM_LOOPTRI_NO_HIDDEN) {
- looptri_mask = looptri_no_hidden_map_get(
- mesh->mpoly, looptri_len, &looptri_mask_active_len);
- }
-
- data_cp.tree = bvhtree_from_mesh_looptri_create_tree(0.0,
- tree_type,
- 6,
- data_cp.vert,
- data_cp.loop,
- data_cp.looptri,
- looptri_len,
- looptri_mask,
- looptri_mask_active_len);
-
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(&mesh->runtime.bvh_cache, data_cp.tree, BVHTREE_FROM_LOOPTRI);
+ if (is_cached == false) {
+ const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
+ int looptri_len = BKE_mesh_runtime_looptri_len(mesh);
+
+ int looptri_mask_active_len = -1;
+ BLI_bitmap *looptri_mask = NULL;
+ if (bvh_cache_type == BVHTREE_FROM_LOOPTRI_NO_HIDDEN) {
+ looptri_mask = looptri_no_hidden_map_get(
+ mesh->mpoly, looptri_len, &looptri_mask_active_len);
}
- BLI_rw_mutex_unlock(&cache_rwlock);
+
+ tree = bvhtree_from_mesh_looptri_ex(data,
+ mesh->mvert,
+ false,
+ mesh->mloop,
+ false,
+ mlooptri,
+ looptri_len,
+ false,
+ looptri_mask,
+ looptri_mask_active_len,
+ 0.0,
+ tree_type,
+ 6,
+ bvh_cache_type,
+ bvh_cache);
+ }
+ else {
+ /* Setup BVHTreeFromMesh */
+ const MLoopTri *mlooptri = BKE_mesh_runtime_looptri_ensure(mesh);
+ bvhtree_from_mesh_looptri_setup_data(
+ data, tree, true, mesh->mvert, false, mesh->mloop, false, mlooptri, false);
}
break;
case BVHTREE_FROM_EM_VERTS:
@@ -1371,23 +1468,113 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
break;
}
- if (data_cp.tree != NULL) {
+ if (data->tree != NULL) {
#ifdef DEBUG
- if (BLI_bvhtree_get_tree_type(data_cp.tree) != tree_type) {
+ if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) {
printf("tree_type %d obtained instead of %d\n",
- BLI_bvhtree_get_tree_type(data_cp.tree),
+ BLI_bvhtree_get_tree_type(data->tree),
tree_type);
}
#endif
- data_cp.cached = true;
- memcpy(data, &data_cp, sizeof(*data));
+ BLI_assert(data->cached);
}
else {
- free_bvhtree_from_mesh(&data_cp);
+ free_bvhtree_from_mesh(data);
memset(data, 0, sizeof(*data));
}
- return data_cp.tree;
+ return tree;
+}
+
+/**
+ * Builds or queries a bvhcache for the cache bvhtree of the request type.
+ */
+BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
+ struct BMEditMesh *em,
+ const int tree_type,
+ const int bvh_cache_type,
+ BVHCache **bvh_cache)
+{
+ BVHTree *tree = NULL;
+ bool is_cached = false;
+
+ memset(data, 0, sizeof(*data));
+
+ if (bvh_cache) {
+ BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
+ is_cached = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
+ BLI_rw_mutex_unlock(&cache_rwlock);
+
+ if (is_cached && tree == NULL) {
+ return tree;
+ }
+ }
+ data->tree = tree;
+ data->em = em;
+ data->cached = is_cached;
+
+ switch (bvh_cache_type) {
+ case BVHTREE_FROM_EM_VERTS:
+ if (is_cached == false) {
+ tree = bvhtree_from_editmesh_verts_ex(
+ data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache);
+ }
+ else {
+ data->nearest_callback = NULL;
+ data->raycast_callback = editmesh_verts_spherecast;
+ }
+ break;
+
+ case BVHTREE_FROM_EM_EDGES:
+ if (is_cached == false) {
+ tree = bvhtree_from_editmesh_edges_ex(
+ data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache);
+ }
+ else {
+ /* Setup BVHTreeFromMesh */
+ data->nearest_callback = NULL; /* TODO */
+ data->raycast_callback = NULL; /* TODO */
+ }
+ break;
+
+ case BVHTREE_FROM_EM_LOOPTRI:
+ if (is_cached == false) {
+ tree = bvhtree_from_editmesh_looptri_ex(
+ data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache);
+ }
+ else {
+ /* Setup BVHTreeFromMesh */
+ data->nearest_callback = editmesh_looptri_nearest_point;
+ data->raycast_callback = editmesh_looptri_spherecast;
+ }
+ break;
+ case BVHTREE_FROM_VERTS:
+ case BVHTREE_FROM_EDGES:
+ case BVHTREE_FROM_FACES:
+ case BVHTREE_FROM_LOOPTRI:
+ case BVHTREE_FROM_LOOPTRI_NO_HIDDEN:
+ case BVHTREE_FROM_LOOSEVERTS:
+ case BVHTREE_FROM_LOOSEEDGES:
+ BLI_assert(false);
+ break;
+ }
+
+ if (data->tree != NULL) {
+#ifdef DEBUG
+ if (BLI_bvhtree_get_tree_type(data->tree) != tree_type) {
+ printf("tree_type %d obtained instead of %d\n",
+ BLI_bvhtree_get_tree_type(data->tree),
+ tree_type);
+ }
+#endif
+ BLI_assert(data->cached);
+ }
+ else {
+ free_bvhtree_from_editmesh(data);
+ memset(data, 0, sizeof(*data));
+ }
+
+ return tree;
}
/** \} */
@@ -1473,12 +1660,13 @@ bool bvhcache_has_tree(const BVHCache *cache, const BVHTree *tree)
* as that will be done when the cache is freed.
*
* A call to this assumes that there was no previous cached tree of the given type
+ * \warning The #BVHTree can be NULL.
*/
void bvhcache_insert(BVHCache **cache_p, BVHTree *tree, int type)
{
BVHCacheItem *item = NULL;
- assert(bvhcache_find(*cache_p, type, &(BVHTree *){0}) == false);
+ BLI_assert(bvhcache_find(*cache_p, type, &(BVHTree *){0}) == false);
item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem");
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index 28bd9c0cea5..a55b5dc7817 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -173,16 +173,6 @@ static void cdDM_getVertCo(DerivedMesh *dm, int index, float r_co[3])
copy_v3_v3(r_co, cddm->mvert[index].co);
}
-static void cdDM_getVertCos(DerivedMesh *dm, float (*r_cos)[3])
-{
- MVert *mv = CDDM_get_verts(dm);
- int i;
-
- for (i = 0; i < dm->numVertData; i++, mv++) {
- copy_v3_v3(r_cos[i], mv->co);
- }
-}
-
static void cdDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -203,278 +193,6 @@ static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
return cddm->pmap;
}
-static bool check_sculpt_object_deformed(Object *object, bool for_construction)
-{
- bool deformed = false;
-
- /* Active modifiers means extra deformation, which can't be handled correct
- * on birth of PBVH and sculpt "layer" levels, so use PBVH only for internal brush
- * stuff and show final DerivedMesh so user would see actual object shape.
- */
- deformed |= object->sculpt->modifiers_active;
-
- if (for_construction) {
- deformed |= object->sculpt->kb != NULL;
- }
- else {
- /* As in case with modifiers, we can't synchronize deformation made against
- * PBVH and non-locked keyblock, so also use PBVH only for brushes and
- * final DM to give final result to user.
- */
- deformed |= object->sculpt->kb && (object->shapeflag & OB_SHAPE_LOCK) == 0;
- }
-
- return deformed;
-}
-
-static bool can_pbvh_draw(Object *ob, DerivedMesh *dm)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- Mesh *me = ob->data;
- bool deformed = check_sculpt_object_deformed(ob, false);
-
- if (deformed) {
- return false;
- }
-
- return cddm->mvert == me->mvert || ob->sculpt->kb;
-}
-
-static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
-
- if (!ob) {
- cddm->pbvh = NULL;
- return NULL;
- }
-
- if (!ob->sculpt) {
- return NULL;
- }
-
- if (ob->sculpt->pbvh) {
- cddm->pbvh = ob->sculpt->pbvh;
- cddm->pbvh_draw = can_pbvh_draw(ob, dm);
- }
-
- /* Sculpting on a BMesh (dynamic-topology) gets a special PBVH */
- if (!cddm->pbvh && ob->sculpt->bm) {
- cddm->pbvh = BKE_pbvh_new();
- cddm->pbvh_draw = true;
-
- BKE_pbvh_build_bmesh(cddm->pbvh,
- ob->sculpt->bm,
- ob->sculpt->bm_smooth_shading,
- ob->sculpt->bm_log,
- ob->sculpt->cd_vert_node_offset,
- ob->sculpt->cd_face_node_offset);
-
- pbvh_show_mask_set(cddm->pbvh, ob->sculpt->show_mask);
- }
-
- /* always build pbvh from original mesh, and only use it for drawing if
- * this derivedmesh is just original mesh. it's the multires subsurf dm
- * that this is actually for, to support a pbvh on a modified mesh */
- if (!cddm->pbvh && ob->type == OB_MESH) {
- Mesh *me = BKE_object_get_original_mesh(ob);
- const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
- MLoopTri *looptri;
- bool deformed;
-
- cddm->pbvh = BKE_pbvh_new();
- cddm->pbvh_draw = can_pbvh_draw(ob, dm);
-
- looptri = MEM_malloc_arrayN(looptris_num, sizeof(*looptri), __func__);
-
- BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
-
- BKE_pbvh_build_mesh(cddm->pbvh,
- me->mpoly,
- me->mloop,
- me->mvert,
- me->totvert,
- &me->vdata,
- &me->ldata,
- looptri,
- looptris_num);
-
- pbvh_show_mask_set(cddm->pbvh, ob->sculpt->show_mask);
-
- deformed = check_sculpt_object_deformed(ob, true);
-
- if (deformed && ob->derivedDeform) {
- DerivedMesh *deformdm = ob->derivedDeform;
- float(*vertCos)[3];
- int totvert;
-
- totvert = deformdm->getNumVerts(deformdm);
- vertCos = MEM_malloc_arrayN(totvert, sizeof(float[3]), "cdDM_getPBVH vertCos");
- deformdm->getVertCos(deformdm, vertCos);
- BKE_pbvh_apply_vertCos(cddm->pbvh, vertCos, totvert);
- MEM_freeN(vertCos);
- }
- }
-
- return cddm->pbvh;
-}
-
-static void cdDM_foreachMappedVert(DerivedMesh *dm,
- void (*func)(void *userData,
- int index,
- const float co[3],
- const float no_f[3],
- const short no_s[3]),
- void *userData,
- DMForeachFlag flag)
-{
- MVert *mv = CDDM_get_verts(dm);
- const int *index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
- int i;
-
- if (index) {
- for (i = 0; i < dm->numVertData; i++, mv++) {
- const short *no = (flag & DM_FOREACH_USE_NORMAL) ? mv->no : NULL;
- const int orig = *index++;
- if (orig == ORIGINDEX_NONE) {
- continue;
- }
- func(userData, orig, mv->co, NULL, no);
- }
- }
- else {
- for (i = 0; i < dm->numVertData; i++, mv++) {
- const short *no = (flag & DM_FOREACH_USE_NORMAL) ? mv->no : NULL;
- func(userData, i, mv->co, NULL, no);
- }
- }
-}
-
-static void cdDM_foreachMappedEdge(
- DerivedMesh *dm,
- void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
- void *userData)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- MVert *mv = cddm->mvert;
- MEdge *med = cddm->medge;
- int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX);
-
- for (i = 0; i < dm->numEdgeData; i++, med++) {
- if (index) {
- orig = *index++;
- if (orig == ORIGINDEX_NONE) {
- continue;
- }
- func(userData, orig, mv[med->v1].co, mv[med->v2].co);
- }
- else {
- func(userData, i, mv[med->v1].co, mv[med->v2].co);
- }
- }
-}
-
-static void cdDM_foreachMappedLoop(DerivedMesh *dm,
- void (*func)(void *userData,
- int vertex_index,
- int face_index,
- const float co[3],
- const float no[3]),
- void *userData,
- DMForeachFlag flag)
-{
- /* We can't use dm->getLoopDataLayout(dm) here,
- * we want to always access dm->loopData, EditDerivedBMesh would
- * return loop data from bmesh itself. */
- const float(*lnors)[3] = (flag & DM_FOREACH_USE_NORMAL) ? DM_get_loop_data_layer(dm, CD_NORMAL) :
- NULL;
-
- const MVert *mv = CDDM_get_verts(dm);
- const MLoop *ml = CDDM_get_loops(dm);
- const MPoly *mp = CDDM_get_polys(dm);
- const int *v_index = DM_get_vert_data_layer(dm, CD_ORIGINDEX);
- const int *f_index = DM_get_poly_data_layer(dm, CD_ORIGINDEX);
- int p_idx, i;
-
- for (p_idx = 0; p_idx < dm->numPolyData; ++p_idx, ++mp) {
- for (i = 0; i < mp->totloop; ++i, ++ml) {
- const int v_idx = v_index ? v_index[ml->v] : ml->v;
- const int f_idx = f_index ? f_index[p_idx] : p_idx;
- const float *no = lnors ? *lnors++ : NULL;
- if (!ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
- func(userData, v_idx, f_idx, mv[ml->v].co, no);
- }
- }
- }
-}
-
-static void cdDM_foreachMappedFaceCenter(
- DerivedMesh *dm,
- void (*func)(void *userData, int index, const float cent[3], const float no[3]),
- void *userData,
- DMForeachFlag flag)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- MVert *mvert = cddm->mvert;
- MPoly *mp;
- MLoop *ml;
- int i, orig, *index;
-
- index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
- mp = cddm->mpoly;
- for (i = 0; i < dm->numPolyData; i++, mp++) {
- float cent[3];
- float *no, _no[3];
-
- if (index) {
- orig = *index++;
- if (orig == ORIGINDEX_NONE) {
- continue;
- }
- }
- else {
- orig = i;
- }
-
- ml = &cddm->mloop[mp->loopstart];
- BKE_mesh_calc_poly_center(mp, ml, mvert, cent);
-
- if (flag & DM_FOREACH_USE_NORMAL) {
- BKE_mesh_calc_poly_normal(mp, ml, mvert, (no = _no));
- }
- else {
- no = NULL;
- }
-
- func(userData, orig, cent, no);
- }
-}
-
-void CDDM_recalc_tessellation_ex(DerivedMesh *dm, const bool do_face_nor_cpy)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
-
- dm->numTessFaceData = BKE_mesh_recalc_tessellation(&dm->faceData,
- &dm->loopData,
- &dm->polyData,
- cddm->mvert,
- dm->numTessFaceData,
- dm->numLoopData,
- dm->numPolyData,
- do_face_nor_cpy);
-
- cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
-
- /* Tessellation recreated faceData, and the active layer indices need to get re-propagated
- * from loops and polys to faces */
- CustomData_bmesh_update_active_layers(&dm->faceData, &dm->loopData);
-}
-
-void CDDM_recalc_tessellation(DerivedMesh *dm)
-{
- CDDM_recalc_tessellation_ex(dm, true);
-}
-
void CDDM_recalc_looptri(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -547,25 +265,13 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->getEdgeDataArray = DM_get_edge_data_layer;
dm->getTessFaceDataArray = DM_get_tessface_data_layer;
- dm->calcNormals = CDDM_calc_normals;
- dm->calcLoopNormals = CDDM_calc_loop_normals;
- dm->calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
- dm->calcLoopTangents = DM_calc_loop_tangents;
- dm->recalcTessellation = CDDM_recalc_tessellation;
dm->recalcLoopTri = CDDM_recalc_looptri;
- dm->getVertCos = cdDM_getVertCos;
dm->getVertCo = cdDM_getVertCo;
dm->getVertNo = cdDM_getVertNo;
- dm->getPBVH = cdDM_getPBVH;
dm->getPolyMap = cdDM_getPolyMap;
- dm->foreachMappedVert = cdDM_foreachMappedVert;
- dm->foreachMappedEdge = cdDM_foreachMappedEdge;
- dm->foreachMappedLoop = cdDM_foreachMappedLoop;
- dm->foreachMappedFaceCenter = cdDM_foreachMappedFaceCenter;
-
dm->release = cdDM_release;
return cddm;
@@ -664,123 +370,12 @@ DerivedMesh *CDDM_from_mesh_ex(Mesh *mesh,
return dm;
}
-DerivedMesh *CDDM_from_curve(Object *ob)
-{
- ListBase disp = {NULL, NULL};
-
- if (ob->runtime.curve_cache) {
- disp = ob->runtime.curve_cache->disp;
- }
-
- return CDDM_from_curve_displist(ob, &disp);
-}
-
-DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase)
-{
- Curve *cu = (Curve *)ob->data;
- DerivedMesh *dm;
- CDDerivedMesh *cddm;
- MVert *allvert;
- MEdge *alledge;
- MLoop *allloop;
- MPoly *allpoly;
- MLoopUV *alluv = NULL;
- int totvert, totedge, totloop, totpoly;
- bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0;
-
- if (BKE_mesh_nurbs_displist_to_mdata(ob,
- dispbase,
- &allvert,
- &totvert,
- &alledge,
- &totedge,
- &allloop,
- &allpoly,
- (use_orco_uv) ? &alluv : NULL,
- &totloop,
- &totpoly) != 0) {
- /* Error initializing mdata. This often happens when curve is empty */
- return CDDM_new(0, 0, 0, 0, 0);
- }
-
- dm = CDDM_new(totvert, totedge, 0, totloop, totpoly);
- dm->deformedOnly = 1;
- dm->dirty |= DM_DIRTY_NORMALS;
-
- cddm = (CDDerivedMesh *)dm;
-
- memcpy(cddm->mvert, allvert, totvert * sizeof(MVert));
- memcpy(cddm->medge, alledge, totedge * sizeof(MEdge));
- memcpy(cddm->mloop, allloop, totloop * sizeof(MLoop));
- memcpy(cddm->mpoly, allpoly, totpoly * sizeof(MPoly));
-
- if (alluv) {
- const char *uvname = "Orco";
- CustomData_add_layer_named(&cddm->dm.loopData, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname);
- }
-
- MEM_freeN(allvert);
- MEM_freeN(alledge);
- MEM_freeN(allloop);
- MEM_freeN(allpoly);
-
- return dm;
-}
-
-static void loops_to_customdata_corners(
- BMesh *bm, CustomData *facedata, int cdindex, const BMLoop *l3[3], int numCol, int numUV)
-{
- const BMLoop *l;
- // BMFace *f = l3[0]->f;
- MTFace *texface;
- MCol *mcol;
- MLoopCol *mloopcol;
- MLoopUV *mloopuv;
- int i, j, hasPCol = CustomData_has_layer(&bm->ldata, CD_PREVIEW_MLOOPCOL);
-
- for (i = 0; i < numUV; i++) {
- texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i);
-
- for (j = 0; j < 3; j++) {
- l = l3[j];
- mloopuv = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPUV, i);
- copy_v2_v2(texface->uv[j], mloopuv->uv);
- }
- }
-
- for (i = 0; i < numCol; i++) {
- mcol = CustomData_get_n(facedata, CD_MCOL, cdindex, i);
-
- for (j = 0; j < 3; j++) {
- l = l3[j];
- mloopcol = CustomData_bmesh_get_n(&bm->ldata, l->head.data, CD_MLOOPCOL, i);
- MESH_MLOOPCOL_TO_MCOL(mloopcol, &mcol[j]);
- }
- }
-
- if (hasPCol) {
- mcol = CustomData_get(facedata, cdindex, CD_PREVIEW_MCOL);
-
- for (j = 0; j < 3; j++) {
- l = l3[j];
- mloopcol = CustomData_bmesh_get(&bm->ldata, l->head.data, CD_PREVIEW_MLOOPCOL);
- MESH_MLOOPCOL_TO_MCOL(mloopcol, &mcol[j]);
- }
- }
-}
-
/* TODO(campbell): remove, use BKE_mesh_from_bmesh_for_eval_nomain instead. */
/* used for both editbmesh and bmesh */
-static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm,
- const bool use_mdisps,
- /* EditBMesh vars for use_tessface */
- const bool use_tessface,
- const int em_tottri,
- const BMLoop *(*em_looptris)[3])
+static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, const bool use_mdisps)
{
- DerivedMesh *dm = CDDM_new(
- bm->totvert, bm->totedge, use_tessface ? em_tottri : 0, bm->totloop, bm->totface);
+ DerivedMesh *dm = CDDM_new(bm->totvert, bm->totedge, 0, bm->totloop, bm->totface);
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
BMIter iter;
@@ -789,11 +384,8 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm,
BMFace *efa;
MVert *mvert = cddm->mvert;
MEdge *medge = cddm->medge;
- MFace *mface = cddm->mface;
MLoop *mloop = cddm->mloop;
MPoly *mpoly = cddm->mpoly;
- int numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL);
- int numUV = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV);
int *index, add_orig;
CustomData_MeshMasks mask = {0};
unsigned int i, j;
@@ -820,11 +412,6 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm,
CustomData_merge(&bm->ldata, &dm->loopData, mask.lmask, CD_CALLOC, dm->numLoopData);
CustomData_merge(&bm->pdata, &dm->polyData, mask.pmask, CD_CALLOC, dm->numPolyData);
- /* add tessellation mface layers */
- if (use_tessface) {
- CustomData_from_bmeshpoly(&dm->faceData, &dm->loopData, em_tottri);
- }
-
index = dm->getVertDataArray(dm, CD_ORIGINDEX);
BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) {
@@ -883,32 +470,6 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm,
}
bm->elem_index_dirty &= ~BM_EDGE;
- /* avoid this where possiblem, takes extra memory */
- if (use_tessface) {
-
- BM_mesh_elem_index_ensure(bm, BM_FACE);
-
- index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- for (i = 0; i < dm->numTessFaceData; i++) {
- MFace *mf = &mface[i];
- const BMLoop **l = em_looptris[i];
- efa = l[0]->f;
-
- mf->v1 = BM_elem_index_get(l[0]->v);
- mf->v2 = BM_elem_index_get(l[1]->v);
- mf->v3 = BM_elem_index_get(l[2]->v);
- mf->v4 = 0;
- mf->mat_nr = efa->mat_nr;
- mf->flag = BM_face_flag_to_mflag(efa);
-
- /* map mfaces to polygons in the same cddm intentionally */
- *index++ = BM_elem_index_get(efa);
-
- loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numUV);
- test_index_face(mf, &dm->faceData, i, 3);
- }
- }
-
index = CustomData_get_layer(&dm->polyData, CD_ORIGINDEX);
j = 0;
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
@@ -948,24 +509,9 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm,
return dm;
}
-struct DerivedMesh *CDDM_from_bmesh(struct BMesh *bm, const bool use_mdisps)
+DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, const bool use_mdisps)
{
- return cddm_from_bmesh_ex(bm,
- use_mdisps,
- false,
- /* these vars are for editmesh only */
- 0,
- NULL);
-}
-
-DerivedMesh *CDDM_from_editbmesh(BMEditMesh *em, const bool use_mdisps, const bool use_tessface)
-{
- return cddm_from_bmesh_ex(em->bm,
- use_mdisps,
- /* editmesh */
- use_tessface,
- em->tottri,
- (const BMLoop *(*)[3])em->looptris);
+ return cddm_from_bmesh_ex(em->bm, use_mdisps);
}
DerivedMesh *CDDM_copy(DerivedMesh *source)
@@ -1014,366 +560,11 @@ DerivedMesh *CDDM_copy(DerivedMesh *source)
return dm;
}
-/* note, the CD_ORIGINDEX layers are all 0, so if there is a direct
- * relationship between mesh data this needs to be set by the caller. */
-DerivedMesh *CDDM_from_template_ex(DerivedMesh *source,
- int numVerts,
- int numEdges,
- int numTessFaces,
- int numLoops,
- int numPolys,
- const CustomData_MeshMasks *mask)
-{
- CDDerivedMesh *cddm = cdDM_create("CDDM_from_template dest");
- DerivedMesh *dm = &cddm->dm;
-
- /* ensure these are created if they are made on demand */
- source->getVertDataArray(source, CD_ORIGINDEX);
- source->getEdgeDataArray(source, CD_ORIGINDEX);
- source->getTessFaceDataArray(source, CD_ORIGINDEX);
- source->getPolyDataArray(source, CD_ORIGINDEX);
-
- /* this does a copy of all non mvert/medge/mface layers */
- DM_from_template_ex(
- dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys, mask);
-
- /* now add mvert/medge/mface layers */
- CustomData_add_layer(&dm->vertData, CD_MVERT, CD_CALLOC, NULL, numVerts);
- CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_CALLOC, NULL, numEdges);
- CustomData_add_layer(&dm->faceData, CD_MFACE, CD_CALLOC, NULL, numTessFaces);
- CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_CALLOC, NULL, numLoops);
- CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_CALLOC, NULL, numPolys);
-
- if (!CustomData_get_layer(&dm->vertData, CD_ORIGINDEX)) {
- CustomData_add_layer(&dm->vertData, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts);
- }
- if (!CustomData_get_layer(&dm->edgeData, CD_ORIGINDEX)) {
- CustomData_add_layer(&dm->edgeData, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges);
- }
- if (!CustomData_get_layer(&dm->faceData, CD_ORIGINDEX)) {
- CustomData_add_layer(&dm->faceData, CD_ORIGINDEX, CD_CALLOC, NULL, numTessFaces);
- }
-
- cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
- cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
- cddm->mface = CustomData_get_layer(&dm->faceData, CD_MFACE);
- cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
- cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
-
- return dm;
-}
-DerivedMesh *CDDM_from_template(
- DerivedMesh *source, int numVerts, int numEdges, int numTessFaces, int numLoops, int numPolys)
-{
- return CDDM_from_template_ex(
- source, numVerts, numEdges, numTessFaces, numLoops, numPolys, &CD_MASK_DERIVEDMESH);
-}
-
-void CDDM_apply_vert_coords(DerivedMesh *dm, float (*vertCoords)[3])
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- MVert *vert;
- int i;
-
- /* this will just return the pointer if it wasn't a referenced layer */
- vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
- cddm->mvert = vert;
-
- for (i = 0; i < dm->numVertData; ++i, ++vert) {
- copy_v3_v3(vert->co, vertCoords[i]);
- }
-
- cddm->dm.dirty |= DM_DIRTY_NORMALS;
-}
-
-void CDDM_apply_vert_normals(DerivedMesh *dm, short (*vertNormals)[3])
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- MVert *vert;
- int i;
-
- /* this will just return the pointer if it wasn't a referenced layer */
- vert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
- cddm->mvert = vert;
-
- for (i = 0; i < dm->numVertData; ++i, ++vert) {
- copy_v3_v3_short(vert->no, vertNormals[i]);
- }
-
- cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
-}
-
-void CDDM_calc_normals_mapping_ex(DerivedMesh *dm, const bool only_face_normals)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- float(*face_nors)[3] = NULL;
-
- if (dm->numVertData == 0) {
- cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
- return;
- }
-
- /* now we skip calculating vertex normals for referenced layer,
- * no need to duplicate verts.
- * WATCH THIS, bmesh only change!,
- * need to take care of the side effects here - campbell */
-#if 0
- /* we don't want to overwrite any referenced layers */
- cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
-#endif
-
-#if 0
- if (dm->numTessFaceData == 0) {
- /* No tessellation on this mesh yet, need to calculate one.
- *
- * Important not to update face normals from polys since it
- * interferes with assigning the new normal layer in the following code.
- */
- CDDM_recalc_tessellation_ex(dm, false);
- }
- else {
- /* A tessellation already exists, it should always have a CD_ORIGINDEX */
- BLI_assert(CustomData_has_layer(&dm->faceData, CD_ORIGINDEX));
- CustomData_free_layers(&dm->faceData, CD_NORMAL, dm->numTessFaceData);
- }
-#endif
-
- face_nors = MEM_malloc_arrayN(dm->numPolyData, sizeof(*face_nors), "face_nors");
-
- /* calculate face normals */
- BKE_mesh_calc_normals_poly(cddm->mvert,
- NULL,
- dm->numVertData,
- CDDM_get_loops(dm),
- CDDM_get_polys(dm),
- dm->numLoopData,
- dm->numPolyData,
- face_nors,
- only_face_normals);
-
- CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_ASSIGN, face_nors, dm->numPolyData);
-
- cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
-}
-
-void CDDM_calc_normals_mapping(DerivedMesh *dm)
-{
- /* use this to skip calculating normals on original vert's, this may need to be changed */
- const bool only_face_normals = CustomData_is_referenced_layer(&dm->vertData, CD_MVERT);
-
- CDDM_calc_normals_mapping_ex(dm, only_face_normals);
-}
-
-#if 0
-/* bmesh note: this matches what we have in trunk */
-void CDDM_calc_normals(DerivedMesh *dm)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- float(*poly_nors)[3];
-
- if (dm->numVertData == 0) {
- return;
- }
-
- /* we don't want to overwrite any referenced layers */
- cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
-
- /* fill in if it exists */
- poly_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL);
- if (!poly_nors) {
- poly_nors = CustomData_add_layer(&dm->polyData, CD_NORMAL, CD_CALLOC, NULL, dm->numPolyData);
- }
-
- BKE_mesh_calc_normals_poly(cddm->mvert,
- dm->numVertData,
- CDDM_get_loops(dm),
- CDDM_get_polys(dm),
- dm->numLoopData,
- dm->numPolyData,
- poly_nors,
- false);
-
- cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
-}
-#else
-
-/* poly normal layer is now only for final display */
-void CDDM_calc_normals(DerivedMesh *dm)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
-
- /* we don't want to overwrite any referenced layers */
- cddm->mvert = CustomData_duplicate_referenced_layer(&dm->vertData, CD_MVERT, dm->numVertData);
-
- BKE_mesh_calc_normals_poly(cddm->mvert,
- NULL,
- dm->numVertData,
- CDDM_get_loops(dm),
- CDDM_get_polys(dm),
- dm->numLoopData,
- dm->numPolyData,
- NULL,
- false);
-
- cddm->dm.dirty &= ~DM_DIRTY_NORMALS;
-}
-
-#endif
-
-void CDDM_calc_loop_normals(DerivedMesh *dm, const bool use_split_normals, const float split_angle)
-{
- CDDM_calc_loop_normals_spacearr(dm, use_split_normals, split_angle, NULL);
-}
-
/* #define DEBUG_CLNORS */
#ifdef DEBUG_CLNORS
# include "BLI_linklist.h"
#endif
-void CDDM_calc_loop_normals_spacearr(DerivedMesh *dm,
- const bool use_split_normals,
- const float split_angle,
- MLoopNorSpaceArray *r_lnors_spacearr)
-{
- MVert *mverts = dm->getVertArray(dm);
- MEdge *medges = dm->getEdgeArray(dm);
- MLoop *mloops = dm->getLoopArray(dm);
- MPoly *mpolys = dm->getPolyArray(dm);
-
- CustomData *ldata, *pdata;
-
- float(*lnors)[3];
- short(*clnor_data)[2];
- float(*pnors)[3];
-
- const int numVerts = dm->getNumVerts(dm);
- const int numEdges = dm->getNumEdges(dm);
- const int numLoops = dm->getNumLoops(dm);
- const int numPolys = dm->getNumPolys(dm);
-
- ldata = dm->getLoopDataLayout(dm);
- if (CustomData_has_layer(ldata, CD_NORMAL)) {
- lnors = CustomData_get_layer(ldata, CD_NORMAL);
- }
- else {
- lnors = CustomData_add_layer(ldata, CD_NORMAL, CD_CALLOC, NULL, numLoops);
- }
-
- /* Compute poly (always needed) and vert normals. */
- /* Note we can't use DM_ensure_normals, since it won't keep computed poly nors... */
- pdata = dm->getPolyDataLayout(dm);
- pnors = CustomData_get_layer(pdata, CD_NORMAL);
- if (!pnors) {
- pnors = CustomData_add_layer(pdata, CD_NORMAL, CD_CALLOC, NULL, numPolys);
- }
- BKE_mesh_calc_normals_poly(mverts,
- NULL,
- numVerts,
- mloops,
- mpolys,
- numLoops,
- numPolys,
- pnors,
- (dm->dirty & DM_DIRTY_NORMALS) ? false : true);
-
- dm->dirty &= ~DM_DIRTY_NORMALS;
-
- clnor_data = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL);
-
- BKE_mesh_normals_loop_split(mverts,
- numVerts,
- medges,
- numEdges,
- mloops,
- lnors,
- numLoops,
- mpolys,
- (const float(*)[3])pnors,
- numPolys,
- use_split_normals,
- split_angle,
- r_lnors_spacearr,
- clnor_data,
- NULL);
-#ifdef DEBUG_CLNORS
- if (r_lnors_spacearr) {
- int i;
- for (i = 0; i < numLoops; i++) {
- if (r_lnors_spacearr->lspacearr[i]->ref_alpha != 0.0f) {
- LinkNode *loops = r_lnors_spacearr->lspacearr[i]->loops;
- printf("Loop %d uses lnor space %p:\n", i, r_lnors_spacearr->lspacearr[i]);
- print_v3("\tfinal lnor", lnors[i]);
- print_v3("\tauto lnor", r_lnors_spacearr->lspacearr[i]->vec_lnor);
- print_v3("\tref_vec", r_lnors_spacearr->lspacearr[i]->vec_ref);
- printf("\talpha: %f\n\tbeta: %f\n\tloops: %p\n",
- r_lnors_spacearr->lspacearr[i]->ref_alpha,
- r_lnors_spacearr->lspacearr[i]->ref_beta,
- r_lnors_spacearr->lspacearr[i]->loops);
- printf("\t\t(shared with loops");
- while (loops) {
- printf(" %d", POINTER_AS_INT(loops->link));
- loops = loops->next;
- }
- printf(")\n");
- }
- else {
- printf("Loop %d has no lnor space\n", i);
- }
- }
- }
-#endif
-}
-
-void CDDM_lower_num_verts(DerivedMesh *dm, int numVerts)
-{
- BLI_assert(numVerts >= 0);
- if (numVerts < dm->numVertData) {
- CustomData_free_elem(&dm->vertData, numVerts, dm->numVertData - numVerts);
- }
-
- dm->numVertData = numVerts;
-}
-
-void CDDM_lower_num_edges(DerivedMesh *dm, int numEdges)
-{
- BLI_assert(numEdges >= 0);
- if (numEdges < dm->numEdgeData) {
- CustomData_free_elem(&dm->edgeData, numEdges, dm->numEdgeData - numEdges);
- }
-
- dm->numEdgeData = numEdges;
-}
-
-void CDDM_lower_num_tessfaces(DerivedMesh *dm, int numTessFaces)
-{
- BLI_assert(numTessFaces >= 0);
- if (numTessFaces < dm->numTessFaceData) {
- CustomData_free_elem(&dm->faceData, numTessFaces, dm->numTessFaceData - numTessFaces);
- }
-
- dm->numTessFaceData = numTessFaces;
-}
-
-void CDDM_lower_num_loops(DerivedMesh *dm, int numLoops)
-{
- BLI_assert(numLoops >= 0);
- if (numLoops < dm->numLoopData) {
- CustomData_free_elem(&dm->loopData, numLoops, dm->numLoopData - numLoops);
- }
-
- dm->numLoopData = numLoops;
-}
-
-void CDDM_lower_num_polys(DerivedMesh *dm, int numPolys)
-{
- BLI_assert(numPolys >= 0);
- if (numPolys < dm->numPolyData) {
- CustomData_free_elem(&dm->polyData, numPolys, dm->numPolyData - numPolys);
- }
-
- dm->numPolyData = numPolys;
-}
-
/* mesh element access functions */
MVert *CDDM_get_vert(DerivedMesh *dm, int index)
@@ -1427,58 +618,3 @@ MPoly *CDDM_get_polys(DerivedMesh *dm)
{
return ((CDDerivedMesh *)dm)->mpoly;
}
-
-void CDDM_set_mvert(DerivedMesh *dm, MVert *mvert)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
-
- if (!CustomData_has_layer(&dm->vertData, CD_MVERT)) {
- CustomData_add_layer(&dm->vertData, CD_MVERT, CD_ASSIGN, mvert, dm->numVertData);
- }
-
- cddm->mvert = mvert;
-}
-
-void CDDM_set_medge(DerivedMesh *dm, MEdge *medge)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
-
- if (!CustomData_has_layer(&dm->edgeData, CD_MEDGE)) {
- CustomData_add_layer(&dm->edgeData, CD_MEDGE, CD_ASSIGN, medge, dm->numEdgeData);
- }
-
- cddm->medge = medge;
-}
-
-void CDDM_set_mface(DerivedMesh *dm, MFace *mface)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
-
- if (!CustomData_has_layer(&dm->faceData, CD_MFACE)) {
- CustomData_add_layer(&dm->faceData, CD_MFACE, CD_ASSIGN, mface, dm->numTessFaceData);
- }
-
- cddm->mface = mface;
-}
-
-void CDDM_set_mloop(DerivedMesh *dm, MLoop *mloop)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
-
- if (!CustomData_has_layer(&dm->loopData, CD_MLOOP)) {
- CustomData_add_layer(&dm->loopData, CD_MLOOP, CD_ASSIGN, mloop, dm->numLoopData);
- }
-
- cddm->mloop = mloop;
-}
-
-void CDDM_set_mpoly(DerivedMesh *dm, MPoly *mpoly)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
-
- if (!CustomData_has_layer(&dm->polyData, CD_MPOLY)) {
- CustomData_add_layer(&dm->polyData, CD_MPOLY, CD_ASSIGN, mpoly, dm->numPolyData);
- }
-
- cddm->mpoly = mpoly;
-}
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 2031576190e..f2098cc2430 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -203,6 +203,9 @@ void BKE_collection_copy_data(Main *bmain,
const Collection *collection_src,
const int flag)
{
+ BLI_assert(((collection_src->flag & COLLECTION_IS_MASTER) != 0) ==
+ ((collection_src->id.flag & LIB_PRIVATE_DATA) != 0));
+
/* Do not copy collection's preview (same behavior as for objects). */
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
BKE_previewimg_id_copy(&collection_dst->id, &collection_src->id);
@@ -338,8 +341,9 @@ Collection *BKE_collection_duplicate(Main *bmain,
const bool do_obdata)
{
/* It's not allowed to copy the master collection. */
+ BLI_assert((collection->id.flag & LIB_PRIVATE_DATA) == 0);
+ BLI_assert((collection->flag & COLLECTION_IS_MASTER) == 0);
if (collection->flag & COLLECTION_IS_MASTER) {
- BLI_assert("!Master collection can't be duplicated");
return NULL;
}
@@ -365,15 +369,6 @@ Collection *BKE_collection_duplicate(Main *bmain,
return collection_new;
}
-Collection *BKE_collection_copy_master(Main *bmain, Collection *collection, const int flag)
-{
- BLI_assert(collection->flag & COLLECTION_IS_MASTER);
-
- Collection *collection_dst = MEM_dupallocN(collection);
- BKE_collection_copy_data(bmain, collection_dst, collection, flag);
- return collection_dst;
-}
-
void BKE_collection_make_local(Main *bmain, Collection *collection, const bool lib_local)
{
BKE_id_make_local_generic(bmain, &collection->id, true, lib_local);
@@ -499,15 +494,11 @@ Collection *BKE_collection_master_add()
/* Not an actual datablock, but owned by scene. */
Collection *master_collection = MEM_callocN(sizeof(Collection), "Master Collection");
STRNCPY(master_collection->id.name, "GRMaster Collection");
+ master_collection->id.flag |= LIB_PRIVATE_DATA;
master_collection->flag |= COLLECTION_IS_MASTER;
return master_collection;
}
-Collection *BKE_collection_master(const Scene *scene)
-{
- return scene->master_collection;
-}
-
Scene *BKE_collection_master_scene_search(const Main *bmain, const Collection *master_collection)
{
BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0);
@@ -584,7 +575,7 @@ bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
static Collection *collection_next_find(Main *bmain, Scene *scene, Collection *collection)
{
- if (scene && collection == BKE_collection_master(scene)) {
+ if (scene && collection == scene->master_collection) {
return bmain->collections.first;
}
else {
@@ -601,7 +592,7 @@ Collection *BKE_collection_object_find(Main *bmain,
collection = collection_next_find(bmain, scene, collection);
}
else if (scene) {
- collection = BKE_collection_master(scene);
+ collection = scene->master_collection;
}
else {
collection = bmain->collections.first;
@@ -743,7 +734,7 @@ void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, O
if (!is_instantiated) {
/* In case we could not find any non-linked collections in which instantiate our ob_dst,
* fallback to scene's master collection... */
- collection_object_add(bmain, BKE_collection_master(scene), ob_dst, 0, true);
+ collection_object_add(bmain, scene->master_collection, ob_dst, 0, true);
}
BKE_main_collection_sync(bmain);
@@ -885,7 +876,7 @@ void BKE_collections_child_remove_nulls(Main *bmain, Collection *collection)
collection_null_children_remove(collection);
}
for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
- collection_null_children_remove(BKE_collection_master(scene));
+ collection_null_children_remove(scene->master_collection);
}
for (collection = bmain->collections.first; collection != NULL;
@@ -893,7 +884,7 @@ void BKE_collections_child_remove_nulls(Main *bmain, Collection *collection)
collection_missing_parents_remove(collection);
}
for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
- collection_missing_parents_remove(BKE_collection_master(scene));
+ collection_missing_parents_remove(scene->master_collection);
}
}
else {
@@ -1169,7 +1160,7 @@ static Collection *collection_from_index_recursive(Collection *collection,
Collection *BKE_collection_from_index(Scene *scene, const int index)
{
int index_current = 0;
- Collection *master_collection = BKE_collection_master(scene);
+ Collection *master_collection = scene->master_collection;
return collection_from_index_recursive(master_collection, index, &index_current);
}
@@ -1363,7 +1354,7 @@ static void scene_collections_array(Scene *scene, Collection ***collections_arra
return;
}
- collection = BKE_collection_master(scene);
+ collection = scene->master_collection;
BLI_assert(collection != NULL);
scene_collection_callback(collection, scene_collections_count, tot);
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index e1e4d138fd9..ccacb85651c 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -62,6 +62,7 @@
#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
@@ -1808,18 +1809,25 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
copy_v3_v3(loc, cob->matrix[3]);
mat4_to_size(size, cob->matrix);
+ /* Select the Euler rotation order, defaulting to the owner. */
+ short rot_order = cob->rotOrder;
+
+ if (data->euler_order != CONSTRAINT_EULER_AUTO) {
+ rot_order = data->euler_order;
+ }
+
/* To allow compatible rotations, must get both rotations in the order of the owner... */
- mat4_to_eulO(obeul, cob->rotOrder, cob->matrix);
+ mat4_to_eulO(obeul, rot_order, cob->matrix);
/* We must get compatible eulers from the beginning because
* some of them can be modified below (see bug T21875). */
- mat4_to_compatible_eulO(eul, obeul, cob->rotOrder, ct->matrix);
+ mat4_to_compatible_eulO(eul, obeul, rot_order, ct->matrix);
if ((data->flag & ROTLIKE_X) == 0) {
eul[0] = obeul[0];
}
else {
if (data->flag & ROTLIKE_OFFSET) {
- rotate_eulO(eul, cob->rotOrder, 'X', obeul[0]);
+ rotate_eulO(eul, rot_order, 'X', obeul[0]);
}
if (data->flag & ROTLIKE_X_INVERT) {
@@ -1832,7 +1840,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
else {
if (data->flag & ROTLIKE_OFFSET) {
- rotate_eulO(eul, cob->rotOrder, 'Y', obeul[1]);
+ rotate_eulO(eul, rot_order, 'Y', obeul[1]);
}
if (data->flag & ROTLIKE_Y_INVERT) {
@@ -1845,7 +1853,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
else {
if (data->flag & ROTLIKE_OFFSET) {
- rotate_eulO(eul, cob->rotOrder, 'Z', obeul[2]);
+ rotate_eulO(eul, rot_order, 'Z', obeul[2]);
}
if (data->flag & ROTLIKE_Z_INVERT) {
@@ -1856,7 +1864,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
/* Good to make eulers compatible again,
* since we don't know how much they were changed above. */
compatible_eul(eul, obeul);
- loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
+ loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order);
}
}
@@ -1927,9 +1935,39 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta
if (VALID_CONS_TARGET(ct)) {
float obsize[3], size[3];
- mat4_to_size(size, ct->matrix);
mat4_to_size(obsize, cob->matrix);
+ /* Compute one uniform scale factor to apply to all three axes. */
+ if (data->flag & SIZELIKE_UNIFORM) {
+ const int all_axes = SIZELIKE_X | SIZELIKE_Y | SIZELIKE_Z;
+ float total = 1.0f;
+
+ /* If all axes are selected, use the determinant. */
+ if ((data->flag & all_axes) == all_axes) {
+ total = fabsf(mat4_to_volume_scale(ct->matrix));
+ }
+ /* Otherwise multiply individual values. */
+ else {
+ mat4_to_size(size, ct->matrix);
+
+ if (data->flag & SIZELIKE_X) {
+ total *= size[0];
+ }
+ if (data->flag & SIZELIKE_Y) {
+ total *= size[1];
+ }
+ if (data->flag & SIZELIKE_Z) {
+ total *= size[2];
+ }
+ }
+
+ copy_v3_fl(size, cbrt(total));
+ }
+ /* Regular per-axis scaling. */
+ else {
+ mat4_to_size(size, ct->matrix);
+ }
+
for (int i = 0; i < 3; i++) {
size[i] = powf(size[i], data->power);
}
@@ -1948,13 +1986,13 @@ static void sizelike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *ta
}
}
- if ((data->flag & SIZELIKE_X) && (obsize[0] != 0)) {
+ if ((data->flag & (SIZELIKE_X | SIZELIKE_UNIFORM)) && (obsize[0] != 0)) {
mul_v3_fl(cob->matrix[0], size[0] / obsize[0]);
}
- if ((data->flag & SIZELIKE_Y) && (obsize[1] != 0)) {
+ if ((data->flag & (SIZELIKE_Y | SIZELIKE_UNIFORM)) && (obsize[1] != 0)) {
mul_v3_fl(cob->matrix[1], size[1] / obsize[1]);
}
- if ((data->flag & SIZELIKE_Z) && (obsize[2] != 0)) {
+ if ((data->flag & (SIZELIKE_Z | SIZELIKE_UNIFORM)) && (obsize[2] != 0)) {
mul_v3_fl(cob->matrix[2], size[2] / obsize[2]);
}
}
@@ -3689,7 +3727,8 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
if (VALID_CONS_TARGET(ct)) {
float *from_min, *from_max, *to_min, *to_max;
float loc[3], eul[3], size[3];
- float dvec[3], sval[3];
+ float dbuf[4], sval[3];
+ float *const dvec = dbuf + 1;
int i;
/* obtain target effect */
@@ -3708,7 +3747,8 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
from_max = data->from_max_scale;
break;
case TRANS_ROTATION:
- mat4_to_eulO(dvec, cob->rotOrder, ct->matrix);
+ BKE_driver_target_matrix_to_rot_channels(
+ ct->matrix, cob->rotOrder, data->from_rotation_mode, -1, true, dbuf);
from_min = data->from_min_rot;
from_max = data->from_max_rot;
break;
@@ -3720,9 +3760,16 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
break;
}
+ /* Select the output Euler rotation order, defaulting to the owner. */
+ short rot_order = cob->rotOrder;
+
+ if (data->to == TRANS_ROTATION && data->to_euler_order != CONSTRAINT_EULER_AUTO) {
+ rot_order = data->to_euler_order;
+ }
+
/* extract components of owner's matrix */
copy_v3_v3(loc, cob->matrix[3]);
- mat4_to_eulO(eul, cob->rotOrder, cob->matrix);
+ mat4_to_eulO(eul, rot_order, cob->matrix);
mat4_to_size(size, cob->matrix);
/* determine where in range current transforms lie */
@@ -3781,7 +3828,7 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
}
/* apply to matrix */
- loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
+ loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order);
}
}
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index f536f21c3e5..bcf6bb338ff 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -1053,7 +1053,7 @@ Collection *CTX_data_collection(const bContext *C)
/* fallback */
Scene *scene = CTX_data_scene(C);
- return BKE_collection_master(scene);
+ return scene->master_collection;
}
enum eContextObjectMode CTX_data_mode_enum_ex(const Object *obedit,
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 09bbc6c0d13..fcbebd24b4a 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -293,7 +293,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
BLI_linklist_free((LinkNode *)datamasks, NULL);
me = BKE_mesh_from_editmesh_with_coords_thin_wrap(em, &data_mask, NULL);
- deformedVerts = editbmesh_get_vertex_cos(em, &numVerts);
+ deformedVerts = editbmesh_vert_coords_alloc(em, &numVerts);
defmats = MEM_mallocN(sizeof(*defmats) * numVerts, "defmats");
for (a = 0; a < numVerts; a++) {
@@ -383,7 +383,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
* state. */
Mesh *me = object_eval.data;
me_eval = BKE_mesh_copy_for_eval(me, true);
- deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts);
+ deformedVerts = BKE_mesh_vert_coords_alloc(me, &numVerts);
defmats = MEM_callocN(sizeof(*defmats) * numVerts, "defmats");
for (a = 0; a < numVerts; a++) {
@@ -485,7 +485,7 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
int a, numVerts;
Mesh *mesh = (Mesh *)object->data;
- *deformcos = BKE_mesh_vertexCos_get(mesh, &numVerts);
+ *deformcos = BKE_mesh_vert_coords_alloc(mesh, &numVerts);
*deformmats = MEM_callocN(sizeof(*(*deformmats)) * numVerts, "defmats");
for (a = 0; a < numVerts; a++) {
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 980e8043a42..3112e1b5ed1 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -4606,18 +4606,13 @@ void BKE_nurb_direction_switch(Nurb *nu)
}
}
-float (*BKE_curve_nurbs_vertexCos_get(ListBase *lb, int *r_numVerts))[3]
+void BKE_curve_nurbs_vert_coords_get(ListBase *lb, float (*vert_coords)[3], int vert_len)
{
- int i, numVerts = *r_numVerts = BKE_nurbList_verts_count(lb);
- float *co, (*cos)[3] = MEM_malloc_arrayN(numVerts, sizeof(*cos), "cu_vcos");
- Nurb *nu;
-
- co = cos[0];
- for (nu = lb->first; nu; nu = nu->next) {
+ float *co = vert_coords[0];
+ for (Nurb *nu = lb->first; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
BezTriple *bezt = nu->bezt;
-
- for (i = 0; i < nu->pntsu; i++, bezt++) {
+ for (int i = 0; i < nu->pntsu; i++, bezt++) {
copy_v3_v3(co, bezt->vec[0]);
co += 3;
copy_v3_v3(co, bezt->vec[1]);
@@ -4628,20 +4623,31 @@ float (*BKE_curve_nurbs_vertexCos_get(ListBase *lb, int *r_numVerts))[3]
}
else {
BPoint *bp = nu->bp;
-
- for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
+ for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
copy_v3_v3(co, bp->vec);
co += 3;
}
}
}
+ BLI_assert(co == vert_coords[vert_len]);
+ UNUSED_VARS_NDEBUG(vert_len);
+}
- return cos;
+float (*BKE_curve_nurbs_vert_coords_alloc(ListBase *lb, int *r_vert_len))[3]
+{
+ const int vert_len = BKE_nurbList_verts_count(lb);
+ float(*vert_coords)[3] = MEM_malloc_arrayN(vert_len, sizeof(*vert_coords), __func__);
+ BKE_curve_nurbs_vert_coords_get(lb, vert_coords, vert_len);
+ *r_vert_len = vert_len;
+ return vert_coords;
}
-void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3])
+void BKE_curve_nurbs_vert_coords_apply_with_mat4(ListBase *lb,
+ const float (*vert_coords)[3],
+ const float mat[4][4],
+ const bool constrain_2d)
{
- const float *co = vertexCos[0];
+ const float *co = vert_coords[0];
Nurb *nu;
int i;
@@ -4650,6 +4656,44 @@ void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3])
BezTriple *bezt = nu->bezt;
for (i = 0; i < nu->pntsu; i++, bezt++) {
+ mul_v3_m4v3(bezt->vec[0], mat, co);
+ co += 3;
+ mul_v3_m4v3(bezt->vec[1], mat, co);
+ co += 3;
+ mul_v3_m4v3(bezt->vec[2], mat, co);
+ co += 3;
+ }
+ }
+ else {
+ BPoint *bp = nu->bp;
+
+ for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
+ mul_v3_m4v3(bp->vec, mat, co);
+ co += 3;
+ }
+ }
+
+ if (constrain_2d) {
+ if (nu->flag & CU_2D) {
+ BKE_nurb_test_2d(nu);
+ }
+ }
+
+ calchandlesNurb_intern(nu, true);
+ }
+}
+
+void BKE_curve_nurbs_vert_coords_apply(ListBase *lb,
+ const float (*vert_coords)[3],
+ const bool constrain_2d)
+{
+ const float *co = vert_coords[0];
+
+ for (Nurb *nu = lb->first; nu; nu = nu->next) {
+ if (nu->type == CU_BEZIER) {
+ BezTriple *bezt = nu->bezt;
+
+ for (int i = 0; i < nu->pntsu; i++, bezt++) {
copy_v3_v3(bezt->vec[0], co);
co += 3;
copy_v3_v3(bezt->vec[1], co);
@@ -4661,28 +4705,33 @@ void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3])
else {
BPoint *bp = nu->bp;
- for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
+ for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
copy_v3_v3(bp->vec, co);
co += 3;
}
}
+ if (constrain_2d) {
+ if (nu->flag & CU_2D) {
+ BKE_nurb_test_2d(nu);
+ }
+ }
+
calchandlesNurb_intern(nu, true);
}
}
-float (*BKE_curve_nurbs_keyVertexCos_get(ListBase *lb, float *key))[3]
+float (*BKE_curve_nurbs_key_vert_coords_alloc(ListBase *lb, float *key, int *r_vert_len))[3]
{
- int i, numVerts = BKE_nurbList_verts_count(lb);
- float *co, (*cos)[3] = MEM_malloc_arrayN(numVerts, sizeof(*cos), "cu_vcos");
- Nurb *nu;
+ int vert_len = BKE_nurbList_verts_count(lb);
+ float(*cos)[3] = MEM_malloc_arrayN(vert_len, sizeof(*cos), __func__);
- co = cos[0];
- for (nu = lb->first; nu; nu = nu->next) {
+ float *co = cos[0];
+ for (Nurb *nu = lb->first; nu; nu = nu->next) {
if (nu->type == CU_BEZIER) {
BezTriple *bezt = nu->bezt;
- for (i = 0; i < nu->pntsu; i++, bezt++) {
+ for (int i = 0; i < nu->pntsu; i++, bezt++) {
copy_v3_v3(co, &key[0]);
co += 3;
copy_v3_v3(co, &key[3]);
@@ -4695,18 +4744,18 @@ float (*BKE_curve_nurbs_keyVertexCos_get(ListBase *lb, float *key))[3]
else {
BPoint *bp = nu->bp;
- for (i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
+ for (int i = 0; i < nu->pntsu * nu->pntsv; i++, bp++) {
copy_v3_v3(co, key);
co += 3;
key += KEYELEM_FLOAT_LEN_BPOINT;
}
}
}
-
+ *r_vert_len = vert_len;
return cos;
}
-void BKE_curve_nurbs_keyVertexTilts_apply(ListBase *lb, float *key)
+void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, float *key)
{
Nurb *nu;
int i;
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 770d8662743..bc982140b29 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -294,7 +294,7 @@ static void layerInterp_mdeformvert(const void **sources,
}
}
- /* delay writing to the destination incase dest is in sources */
+ /* Delay writing to the destination in case dest is in sources. */
/* now we know how many unique deform weights there are, so realloc */
if (dvert->dw && (dvert->totweight == totweight)) {
@@ -441,7 +441,7 @@ static void layerInterp_tface(
}
}
- /* delay writing to the destination incase dest is in sources */
+ /* Delay writing to the destination in case dest is in sources. */
*tf = *(MTFace *)(*sources);
memcpy(tf->uv, uv, sizeof(tf->uv));
}
@@ -548,7 +548,7 @@ static void layerInterp_origspace_face(
}
}
- /* delay writing to the destination in case dest is in sources */
+ /* Delay writing to the destination in case dest is in sources. */
memcpy(osf->uv, uv, sizeof(osf->uv));
}
@@ -908,7 +908,7 @@ static void layerInterp_mloopcol(
/* Subdivide smooth or fractal can cause problems without clamping
* although weights should also not cause this situation */
- /* also delay writing to the destination incase dest is in sources */
+ /* Also delay writing to the destination in case dest is in sources. */
mc->r = round_fl_to_uchar_clamp(col.r);
mc->g = round_fl_to_uchar_clamp(col.g);
mc->b = round_fl_to_uchar_clamp(col.b);
@@ -1008,7 +1008,7 @@ static void layerInterp_mloopuv(
}
}
- /* delay writing to the destination incase dest is in sources */
+ /* Delay writing to the destination in case dest is in sources. */
copy_v2_v2(((MLoopUV *)dest)->uv, uv);
((MLoopUV *)dest)->flag = flag;
}
@@ -1104,7 +1104,7 @@ static void layerInterp_mloop_origspace(
}
}
- /* delay writing to the destination incase dest is in sources */
+ /* Delay writing to the destination in case dest is in sources. */
copy_v2_v2(((OrigSpaceLoop *)dest)->uv, uv);
}
/* --- end copy */
@@ -1152,7 +1152,7 @@ static void layerInterp_mcol(
}
}
- /* delay writing to the destination incase dest is in sources */
+ /* Delay writing to the destination in case dest is in sources. */
for (j = 0; j < 4; ++j) {
/* Subdivide smooth or fractal can cause problems without clamping
@@ -1220,7 +1220,7 @@ static void layerInterp_bweight(const void **sources,
}
}
- /* delay writing to the destination incase dest is in sources */
+ /* Delay writing to the destination in case dest is in sources. */
*((float *)dest) = f;
}
@@ -1251,7 +1251,7 @@ static void layerInterp_shapekey(const void **sources,
}
}
- /* delay writing to the destination incase dest is in sources */
+ /* Delay writing to the destination in case dest is in sources. */
copy_v3_v3((float *)dest, co);
}
@@ -1289,7 +1289,7 @@ static void layerInterp_mvert_skin(const void **sources,
madd_v3_v3fl(radius, vs_src->radius, w);
}
- /* delay writing to the destination incase dest is in sources */
+ /* Delay writing to the destination in case dest is in sources. */
vs_dst = dest;
copy_v3_v3(vs_dst->radius, radius);
vs_dst->flag &= ~MVERT_SKIN_ROOT;
@@ -2828,9 +2828,7 @@ void CustomData_interp(const CustomData *source,
const void *source_buf[SOURCE_BUF_SIZE];
const void **sources = source_buf;
- /* slow fallback in case we're interpolating a ridiculous number of
- * elements
- */
+ /* Slow fallback in case we're interpolating a ridiculous number of elements. */
if (count > SOURCE_BUF_SIZE) {
sources = MEM_malloc_arrayN(count, sizeof(*sources), __func__);
}
@@ -3828,9 +3826,7 @@ void CustomData_bmesh_interp(CustomData *data,
void *source_buf[SOURCE_BUF_SIZE];
const void **sources = (const void **)source_buf;
- /* slow fallback in case we're interpolating a ridiculous number of
- * elements
- */
+ /* Slow fallback in case we're interpolating a ridiculous number of elements. */
if (count > SOURCE_BUF_SIZE) {
sources = MEM_malloc_arrayN(count, sizeof(*sources), __func__);
}
@@ -4185,7 +4181,7 @@ bool CustomData_verify_versions(struct CustomData *data, int index)
if (!typeInfo->defaultname && (index > 0) && data->layers[index - 1].type == layer->type) {
keeplayer = false; /* multiple layers of which we only support one */
}
- /* This is a pre-emptive fix for cases that should not happen
+ /* This is a preemptive fix for cases that should not happen
* (layers that should not be written in .blend files),
* but can happen due to bugs (see e.g. T62318).
* Also for forward compatibility, in future,
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 83a10344b96..cbd3c91acc7 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -892,8 +892,7 @@ static void curve_calc_modifiers_pre(
* tilts, which is passed through in the modifier stack.
* this is also the reason curves do not use a virtual
* shape key modifier yet. */
- deformedVerts = BKE_curve_nurbs_keyVertexCos_get(nurb, keyVerts);
- numVerts = BKE_nurbList_verts_count(nurb);
+ deformedVerts = BKE_curve_nurbs_key_vert_coords_alloc(nurb, keyVerts, &numVerts);
}
}
@@ -909,7 +908,7 @@ static void curve_calc_modifiers_pre(
}
if (!deformedVerts) {
- deformedVerts = BKE_curve_nurbs_vertexCos_get(nurb, &numVerts);
+ deformedVerts = BKE_curve_nurbs_vert_coords_alloc(nurb, &numVerts);
}
mti->deformVerts(md, &mectx, NULL, deformedVerts, numVerts);
@@ -921,11 +920,11 @@ static void curve_calc_modifiers_pre(
}
if (deformedVerts) {
- BK_curve_nurbs_vertexCos_apply(nurb, deformedVerts);
+ BKE_curve_nurbs_vert_coords_apply(nurb, deformedVerts, false);
MEM_freeN(deformedVerts);
}
if (keyVerts) { /* these are not passed through modifier stack */
- BKE_curve_nurbs_keyVertexTilts_apply(nurb, keyVerts);
+ BKE_curve_nurbs_key_vert_tilts_apply(nurb, keyVerts);
}
if (keyVerts) {
@@ -933,18 +932,18 @@ static void curve_calc_modifiers_pre(
}
}
-static float (*displist_get_allverts(ListBase *dispbase, int *totvert))[3]
+static float (*displist_vert_coords_alloc(ListBase *dispbase, int *r_vert_len))[3]
{
DispList *dl;
float(*allverts)[3], *fp;
- *totvert = 0;
+ *r_vert_len = 0;
for (dl = dispbase->first; dl; dl = dl->next) {
- *totvert += (dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr;
+ *r_vert_len += (dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr;
}
- allverts = MEM_mallocN((*totvert) * sizeof(float) * 3, "displist_get_allverts allverts");
+ allverts = MEM_mallocN((*r_vert_len) * sizeof(float) * 3, "displist_vert_coords_alloc allverts");
fp = (float *)allverts;
for (dl = dispbase->first; dl; dl = dl->next) {
int offs = 3 * ((dl->type == DL_INDEX3) ? dl->nr : dl->parts * dl->nr);
@@ -955,7 +954,7 @@ static float (*displist_get_allverts(ListBase *dispbase, int *totvert))[3]
return allverts;
}
-static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
+static void displist_vert_coords_apply(ListBase *dispbase, float (*allverts)[3])
{
DispList *dl;
const float *fp;
@@ -1027,7 +1026,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
* we need to create a Mesh for each curve that uses modifiers. */
if (modified == NULL /* && need_normal */) {
if (vertCos != NULL) {
- displist_apply_allverts(dispbase, vertCos);
+ displist_vert_coords_apply(dispbase, vertCos);
}
if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
@@ -1041,7 +1040,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
(mti->type == eModifierTypeType_DeformOrConstruct && !modified)) {
if (modified) {
if (!vertCos) {
- vertCos = BKE_mesh_vertexCos_get(modified, &totvert);
+ vertCos = BKE_mesh_vert_coords_alloc(modified, &totvert);
}
if (need_normal) {
BKE_mesh_ensure_normals(modified);
@@ -1050,7 +1049,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
}
else {
if (!vertCos) {
- vertCos = displist_get_allverts(dispbase, &totvert);
+ vertCos = displist_vert_coords_alloc(dispbase, &totvert);
}
mti->deformVerts(md, &mectx_deform, NULL, vertCos, totvert);
}
@@ -1071,12 +1070,12 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
BKE_id_free(NULL, modified);
modified = temp_mesh;
- BKE_mesh_apply_vert_coords(modified, vertCos);
+ BKE_mesh_vert_coords_apply(modified, vertCos);
}
}
else {
if (vertCos) {
- displist_apply_allverts(dispbase, vertCos);
+ displist_vert_coords_apply(dispbase, vertCos);
}
if (ELEM(ob->type, OB_CURVE, OB_FONT) && (cu->flag & CU_DEFORM_FILL)) {
@@ -1115,13 +1114,13 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
BKE_id_free(NULL, modified);
modified = temp_mesh;
- BKE_mesh_apply_vert_coords(modified, vertCos);
+ BKE_mesh_vert_coords_apply(modified, vertCos);
BKE_mesh_calc_normals_mapping_simple(modified);
MEM_freeN(vertCos);
}
else {
- displist_apply_allverts(dispbase, vertCos);
+ displist_vert_coords_apply(dispbase, vertCos);
MEM_freeN(vertCos);
vertCos = NULL;
}
@@ -1129,15 +1128,6 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph,
if (r_final) {
if (modified) {
- /* see: mesh_calc_modifiers */
- if (modified->totface == 0) {
- BKE_mesh_tessface_calc(modified);
- }
- /* Even if tessellation is not needed, some modifiers might have modified CD layers
- * (like mloopcol or mloopuv), hence we have to update those. */
- else if (modified->runtime.cd_dirty_vert & CD_MASK_TESSLOOPNORMAL) {
- BKE_mesh_tessface_calc(modified);
- }
/* XXX2.8(Sybren): make sure the face normals are recalculated as well */
BKE_mesh_ensure_normals(modified);
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 04cbdbb6bcd..91b169590ac 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -2755,7 +2755,7 @@ static bool dynamicPaint_symmetrizeAdjData(PaintAdjData *ed, int active_points)
for (int i = 0, idx = ed->n_index[index]; i < ed->n_num[index]; i++) {
const int target = ed->n_target[idx + i];
- assert(!(ed->flags[target] & ADJ_BORDER_PIXEL));
+ BLI_assert(!(ed->flags[target] & ADJ_BORDER_PIXEL));
if (!dynamicPaint_pointHasNeighbor(ed, target, index)) {
new_n_num[target]++;
@@ -2782,7 +2782,7 @@ static bool dynamicPaint_symmetrizeAdjData(PaintAdjData *ed, int active_points)
new_n_num[index] = ed->n_num[index];
}
- assert(n_pos == total_targets);
+ BLI_assert(n_pos == total_targets);
/* Add symmetrized - this loop behavior must exactly match the count pass above */
for (int index = 0; index < active_points; index++) {
@@ -5572,7 +5572,7 @@ static void dynamic_paint_border_cb(void *__restrict userdata,
PaintPoint *pPoint2 = &((PaintPoint *)sData->type_data)[target];
- assert(!(sData->adj_data->flags[target] & ADJ_BORDER_PIXEL));
+ BLI_assert(!(sData->adj_data->flags[target] & ADJ_BORDER_PIXEL));
madd_v3_v3fl(mix_color, pPoint2->color, pPoint2->color[3]);
mix_color[3] += pPoint2->color[3];
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 06f297b23e0..2df3d2f0fe9 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -517,8 +517,8 @@ static void cage_mapped_verts_callback(void *userData,
}
}
-float (*BKE_editmesh_vertexCos_get(
- struct Depsgraph *depsgraph, BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
+float (*BKE_editmesh_vert_coords_alloc(
+ struct Depsgraph *depsgraph, BMEditMesh *em, Scene *scene, int *r_vert_len))[3]
{
Mesh *cage;
BLI_bitmap *visit_bitmap;
@@ -540,8 +540,8 @@ float (*BKE_editmesh_vertexCos_get(
MEM_freeN(visit_bitmap);
- if (r_numVerts) {
- *r_numVerts = em->bm->totvert;
+ if (r_vert_len) {
+ *r_vert_len = em->bm->totvert;
}
return cos_cage;
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index b8234ccc5bb..866c494d354 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -39,7 +39,7 @@ BMEditMesh *BKE_editmesh_create(BMesh *bm, const bool do_tessellate)
em->bm = bm;
if (do_tessellate) {
- BKE_editmesh_tessface_calc(em);
+ BKE_editmesh_looptri_calc(em);
}
return em;
@@ -61,11 +61,10 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em)
/* The tessellation is NOT calculated on the copy here,
* because currently all the callers of this function use
- * it to make a backup copy of the BMEditMesh to restore
- * it in the case of errors in an operation. For perf
- * reasons, in that case it makes more sense to do the
- * tessellation only when/if that copy ends up getting
- * used.*/
+ * it to make a backup copy of the #BMEditMesh to restore
+ * it in the case of errors in an operation. For performance reasons,
+ * in that case it makes more sense to do the
+ * tessellation only when/if that copy ends up getting used. */
em_copy->looptris = NULL;
return em_copy;
@@ -97,8 +96,8 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em)
BMesh *bm = em->bm;
- /* this assumes all faces can be scan-filled, which isn't always true,
- * worst case we over alloc a little which is acceptable */
+ /* This assumes all faces can be scan-filled, which isn't always true,
+ * worst case we over allocate a little which is acceptable. */
const int looptris_tot = poly_to_tri_count(bm->totface, bm->totloop);
const int looptris_tot_prev_alloc = em->looptris ?
(MEM_allocN_len(em->looptris) / sizeof(*em->looptris)) :
@@ -109,7 +108,7 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em)
/* this means no reallocs for quad dominant models, for */
if ((em->looptris != NULL) &&
/* (*em->tottri >= looptris_tot)) */
- /* check against alloc'd size incase we over alloc'd a little */
+ /* Check against allocated size in case we over allocated a little. */
((looptris_tot_prev_alloc >= looptris_tot) &&
(looptris_tot_prev_alloc <= looptris_tot * 2))) {
looptris = em->looptris;
@@ -127,7 +126,7 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em)
BM_mesh_calc_tessellation(em->bm, em->looptris, &em->tottri);
}
-void BKE_editmesh_tessface_calc(BMEditMesh *em)
+void BKE_editmesh_looptri_calc(BMEditMesh *em)
{
editmesh_tessface_calc_intern(em);
@@ -210,7 +209,7 @@ void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype)
}
}
-float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3]
+float (*BKE_editmesh_vert_coords_alloc_orco(BMEditMesh *em, int *r_vert_len))[3]
{
BMIter iter;
BMVert *eve;
@@ -223,7 +222,7 @@ float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3]
copy_v3_v3(orco[i], eve->co);
}
- *r_numVerts = em->bm->totvert;
+ *r_vert_len = em->bm->totvert;
return orco;
}
diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c
index f23276d7be0..5af4e4c0023 100644
--- a/source/blender/blenkernel/intern/editmesh_bvh.c
+++ b/source/blender/blenkernel/intern/editmesh_bvh.c
@@ -73,7 +73,7 @@ BMBVHTree *BKE_bmbvh_new_ex(BMesh *bm,
BMFace *f_test, *f_test_prev;
bool test_fn_ret;
- /* BKE_editmesh_tessface_calc() must be called already */
+ /* BKE_editmesh_looptri_calc() must be called already */
BLI_assert(looptris_tot != 0 || bm->totface == 0);
if (cos_cage) {
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 9580ea763fb..b596eeb9e35 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -382,8 +382,8 @@ FCurve *rna_get_fcurve_context_ui(bContext *C,
}
/* there must be some RNA-pointer + property combon */
- if (prop && tptr.id.data && RNA_property_animateable(&tptr, prop)) {
- AnimData *adt = BKE_animdata_from_id(tptr.id.data);
+ if (prop && tptr.owner_id && RNA_property_animateable(&tptr, prop)) {
+ AnimData *adt = BKE_animdata_from_id(tptr.owner_id);
int step = (
/* Always 1 in case we have no context (can't check in 'ancestors' of given RNA ptr). */
C ? 2 : 1);
@@ -391,7 +391,7 @@ FCurve *rna_get_fcurve_context_ui(bContext *C,
if (!adt && C) {
path = BKE_animdata_driver_path_hack(C, &tptr, prop, NULL);
- adt = BKE_animdata_from_id(tptr.id.data);
+ adt = BKE_animdata_from_id(tptr.owner_id);
step--;
}
@@ -438,7 +438,7 @@ FCurve *rna_get_fcurve_context_ui(bContext *C,
if (tpath && tpath != path) {
MEM_freeN(path);
path = tpath;
- adt = BKE_animdata_from_id(tptr.id.data);
+ adt = BKE_animdata_from_id(tptr.owner_id);
}
else {
adt = NULL;
@@ -1714,7 +1714,10 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
* of scale over all three axes unless the matrix includes shear. */
return cbrtf(mat4_to_volume_scale(mat));
}
- else if (dtar->transChan >= DTAR_TRANSCHAN_SCALEX) {
+ else if (ELEM(dtar->transChan,
+ DTAR_TRANSCHAN_SCALEX,
+ DTAR_TRANSCHAN_SCALEY,
+ DTAR_TRANSCHAN_SCALEZ)) {
/* Extract scale, and choose the right axis,
* inline 'mat4_to_size'. */
return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]);
@@ -1728,15 +1731,25 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
* b) [NOT USED] directly use the original values (no decomposition)
* - only an option for "transform space", if quality is really bad with a)
*/
- float eul[3];
+ float quat[4];
+ int channel;
- mat4_to_eulO(eul, rot_order, mat);
+ if (dtar->transChan == DTAR_TRANSCHAN_ROTW) {
+ channel = 0;
+ }
+ else {
+ channel = 1 + dtar->transChan - DTAR_TRANSCHAN_ROTX;
+ BLI_assert(channel < 4);
+ }
- if (use_eulers) {
- compatible_eul(eul, oldEul);
+ BKE_driver_target_matrix_to_rot_channels(
+ mat, rot_order, dtar->rotation_mode, channel, false, quat);
+
+ if (use_eulers && dtar->rotation_mode == DTAR_ROTMODE_AUTO) {
+ compatible_eul(quat + 1, oldEul);
}
- return eul[dtar->transChan - DTAR_TRANSCHAN_ROTX];
+ return quat[channel];
}
else {
/* extract location and choose right axis */
@@ -1744,6 +1757,71 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
}
}
+/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */
+static void quaternion_to_angles(float quat[4], int channel)
+{
+ if (channel < 0) {
+ quat[0] = 2.0f * saacosf(quat[0]);
+
+ for (int i = 1; i < 4; i++) {
+ quat[i] = 2.0f * saasinf(quat[i]);
+ }
+ }
+ else if (channel == 0) {
+ quat[0] = 2.0f * saacosf(quat[0]);
+ }
+ else {
+ quat[channel] = 2.0f * saasinf(quat[channel]);
+ }
+}
+
+/* Compute channel values for a rotational Transform Channel driver variable. */
+void BKE_driver_target_matrix_to_rot_channels(
+ float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4])
+{
+ float *const quat = r_buf;
+ float *const eul = r_buf + 1;
+
+ zero_v4(r_buf);
+
+ if (rotation_mode == DTAR_ROTMODE_AUTO) {
+ mat4_to_eulO(eul, auto_order, mat);
+ }
+ else if (rotation_mode >= DTAR_ROTMODE_EULER_MIN && rotation_mode <= DTAR_ROTMODE_EULER_MAX) {
+ mat4_to_eulO(eul, rotation_mode, mat);
+ }
+ else if (rotation_mode == DTAR_ROTMODE_QUATERNION) {
+ mat4_to_quat(quat, mat);
+
+ /* For Transformation constraint convenience, convert to pseudo-angles. */
+ if (angles) {
+ quaternion_to_angles(quat, channel);
+ }
+ }
+ else if (rotation_mode >= DTAR_ROTMODE_SWING_TWIST_X &&
+ rotation_mode <= DTAR_ROTMODE_SWING_TWIST_Z) {
+ int axis = rotation_mode - DTAR_ROTMODE_SWING_TWIST_X;
+ float raw_quat[4], twist;
+
+ mat4_to_quat(raw_quat, mat);
+
+ if (channel == axis + 1) {
+ /* If only the twist angle is needed, skip computing swing. */
+ twist = quat_split_swing_and_twist(raw_quat, axis, NULL, NULL);
+ }
+ else {
+ twist = quat_split_swing_and_twist(raw_quat, axis, quat, NULL);
+
+ quaternion_to_angles(quat, channel);
+ }
+
+ quat[axis + 1] = twist;
+ }
+ else {
+ BLI_assert(false);
+ }
+}
+
/* ......... */
/* Table of Driver Variable Type Info Data */
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 220584bac6a..a00be90297b 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -152,19 +152,19 @@ bool BKE_gpencil_free_strokes(bGPDframe *gpf)
}
/* Free strokes and colors belonging to a gp-frame */
-bool BKE_gpencil_free_frame_runtime_data(bGPDframe *derived_gpf)
+bool BKE_gpencil_free_frame_runtime_data(bGPDframe *gpf_eval)
{
bGPDstroke *gps_next;
- if (!derived_gpf) {
+ if (!gpf_eval) {
return false;
}
/* free strokes */
- for (bGPDstroke *gps = derived_gpf->strokes.first; gps; gps = gps_next) {
+ for (bGPDstroke *gps = gpf_eval->strokes.first; gps; gps = gps_next) {
gps_next = gps->next;
BKE_gpencil_free_stroke(gps);
}
- BLI_listbase_clear(&derived_gpf->strokes);
+ BLI_listbase_clear(&gpf_eval->strokes);
return true;
}
@@ -267,7 +267,8 @@ bGPDframe *BKE_gpencil_frame_addnew(bGPDlayer *gpl, int cframe)
/* check whether frame was added successfully */
if (state == -1) {
- CLOG_ERROR(&LOG, "Frame (%d) existed already for this layer. Using existing frame", cframe);
+ CLOG_ERROR(
+ &LOG, "Frame (%d) existed already for this layer_active. Using existing frame", cframe);
/* free the newly created one, and use the old one instead */
MEM_freeN(gpf);
@@ -1040,6 +1041,37 @@ void BKE_gpencil_layer_setactive(bGPdata *gpd, bGPDlayer *active)
}
}
+/* Set locked layers for autolock mode. */
+void BKE_gpencil_layer_autolock_set(bGPdata *gpd)
+{
+ BLI_assert(gpd != NULL);
+
+ bGPDlayer *gpl;
+
+ if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
+ bGPDlayer *layer_active = BKE_gpencil_layer_getactive(gpd);
+
+ /* Lock all other layers */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ /* unlock active layer */
+ if (gpl == layer_active) {
+ gpl->flag &= ~GP_LAYER_LOCKED;
+ }
+ else {
+ gpl->flag |= GP_LAYER_LOCKED;
+ }
+ }
+ }
+ else {
+ /* If disable is better unlock all layers by default or it looks there is
+ * a problem in the UI because the user expects all layers will be unlocked
+ */
+ for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
+ gpl->flag &= ~GP_LAYER_LOCKED;
+ }
+ }
+}
+
/* delete the active gp-layer */
void BKE_gpencil_layer_delete(bGPdata *gpd, bGPDlayer *gpl)
{
@@ -1190,38 +1222,34 @@ Material *BKE_gpencil_object_material_ensure_from_active_input_brush(Main *bmain
brush->gpencil_settings->flag &= ~GP_BRUSH_MATERIAL_PINNED;
}
}
- return BKE_gpencil_object_material_ensure_from_active_input_material(bmain, ob);
+ return BKE_gpencil_object_material_ensure_from_active_input_material(ob);
}
/**
* Guaranteed to return a material assigned to object. Returns never NULL.
* Only use this for materials unrelated to user input.
*/
-Material *BKE_gpencil_object_material_ensure_from_active_input_material(Main *bmain, Object *ob)
+Material *BKE_gpencil_object_material_ensure_from_active_input_material(Object *ob)
{
Material *ma = give_current_material(ob, ob->actcol);
if (ma) {
return ma;
}
- /* If the slot is empty, remove because will be added again,
- * if not, we will get an empty slot. */
- if ((ob->totcol > 0) && (ob->actcol == ob->totcol)) {
- BKE_object_material_slot_remove(bmain, ob);
- }
- return BKE_gpencil_object_material_new(bmain, ob, "Material", NULL);
+
+ return &defgpencil_material;
}
/* Get active color, and add all default settings if we don't find anything */
-Material *BKE_gpencil_object_material_ensure_active(Main *bmain, Object *ob)
+Material *BKE_gpencil_object_material_ensure_active(Object *ob)
{
Material *ma = NULL;
/* sanity checks */
- if (ELEM(NULL, bmain, ob)) {
+ if (ob == NULL) {
return NULL;
}
- ma = BKE_gpencil_object_material_ensure_from_active_input_material(bmain, ob);
+ ma = BKE_gpencil_object_material_ensure_from_active_input_material(ob);
if (ma->gp_style == NULL) {
BKE_material_init_gpencil_settings(ma);
}
@@ -2048,33 +2076,55 @@ bool BKE_gpencil_smooth_stroke_strength(bGPDstroke *gps, int point_index, float
bGPDspoint *ptb = &gps->points[point_index];
/* Do nothing if not enough points */
- if (gps->totpoints <= 2) {
+ if ((gps->totpoints <= 2) || (point_index < 1)) {
return false;
}
+ /* Only affect endpoints by a fraction of the normal influence */
+ float inf = influence;
+ if ((point_index == 0) || (point_index == gps->totpoints - 1)) {
+ inf *= 0.01f;
+ }
+ /* Limit max influence to reduce pop effect. */
+ CLAMP_MAX(inf, 0.98f);
- /* Compute theoretical optimal value using distances */
- bGPDspoint *pta, *ptc;
- int before = point_index - 1;
- int after = point_index + 1;
+ float total = 0.0f;
+ float max_strength = 0.0f;
+ const int steps = 4;
+ const float average_fac = 1.0f / (float)(steps * 2 + 1);
+ int step;
- CLAMP_MIN(before, 0);
- CLAMP_MAX(after, gps->totpoints - 1);
+ /* add the point itself */
+ total += ptb->strength * average_fac;
+ max_strength = ptb->strength;
- pta = &gps->points[before];
- ptc = &gps->points[after];
+ /* n-steps before/after current point */
+ for (step = 1; step <= steps; step++) {
+ bGPDspoint *pt1, *pt2;
+ int before = point_index - step;
+ int after = point_index + step;
- /* the optimal value is the corresponding to the interpolation of the strength
- * at the distance of point b
- */
- float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
- /* sometimes the factor can be wrong due stroke geometry, so use middle point */
- if ((fac < 0.0f) || (fac > 1.0f)) {
- fac = 0.5f;
+ 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) */
+ total += pt1->strength * average_fac;
+ total += pt2->strength * average_fac;
+ /* Save max value. */
+ if (max_strength < pt1->strength) {
+ max_strength = pt1->strength;
+ }
+ if (max_strength < pt2->strength) {
+ max_strength = pt2->strength;
+ }
}
- 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;
+ /* Based on influence factor, blend between original and optimal smoothed value. */
+ ptb->strength = interpf(ptb->strength, total, inf);
+ /* Clamp to maximum stroke strength to avoid weird results. */
+ CLAMP_MAX(ptb->strength, max_strength);
return true;
}
@@ -2089,31 +2139,52 @@ bool BKE_gpencil_smooth_stroke_thickness(bGPDstroke *gps, int point_index, float
if ((gps->totpoints <= 2) || (point_index < 1)) {
return false;
}
+ /* Only affect endpoints by a fraction of the normal influence */
+ float inf = influence;
+ if ((point_index == 0) || (point_index == gps->totpoints - 1)) {
+ inf *= 0.01f;
+ }
+ /* Limit max influence to reduce pop effect. */
+ CLAMP_MAX(inf, 0.98f);
- /* Compute theoretical optimal value using distances */
- bGPDspoint *pta, *ptc;
- int before = point_index - 1;
- int after = point_index + 1;
+ float total = 0.0f;
+ float max_pressure = 0.0f;
+ const int steps = 4;
+ const float average_fac = 1.0f / (float)(steps * 2 + 1);
+ int step;
- CLAMP_MIN(before, 0);
- CLAMP_MAX(after, gps->totpoints - 1);
+ /* add the point itself */
+ total += ptb->pressure * average_fac;
+ max_pressure = ptb->pressure;
- pta = &gps->points[before];
- ptc = &gps->points[after];
+ /* n-steps before/after current point */
+ for (step = 1; step <= steps; step++) {
+ bGPDspoint *pt1, *pt2;
+ int before = point_index - step;
+ int after = point_index + step;
- /* 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);
- /* sometimes the factor can be wrong due stroke geometry, so use middle point */
- if ((fac < 0.0f) || (fac > 1.0f)) {
- fac = 0.5f;
- }
- float optimal = interpf(ptc->pressure, pta->pressure, fac);
+ CLAMP_MIN(before, 0);
+ CLAMP_MAX(after, gps->totpoints - 1);
- /* Based on influence factor, blend between original and optimal */
- ptb->pressure = interpf(optimal, ptb->pressure, influence);
+ pt1 = &gps->points[before];
+ pt2 = &gps->points[after];
+
+ /* add both these points to the average-sum (s += p[i]/n) */
+ total += pt1->pressure * average_fac;
+ total += pt2->pressure * average_fac;
+ /* Save max value. */
+ if (max_pressure < pt1->pressure) {
+ max_pressure = pt1->pressure;
+ }
+ if (max_pressure < pt2->pressure) {
+ max_pressure = pt2->pressure;
+ }
+ }
+ /* Based on influence factor, blend between original and optimal smoothed value. */
+ ptb->pressure = interpf(ptb->pressure, total, inf);
+ /* Clamp to maximum stroke thickness to avoid weird results. */
+ CLAMP_MAX(ptb->pressure, max_pressure);
return true;
}
@@ -2229,6 +2300,7 @@ void BKE_gpencil_material_index_reassign(bGPdata *gpd, int totcol, int index)
/* reassign strokes */
if ((gps->mat_nr > index) || (gps->mat_nr > totcol - 1)) {
gps->mat_nr--;
+ CLAMP_MIN(gps->mat_nr, 0);
}
}
}
@@ -3134,3 +3206,397 @@ void BKE_gpencil_merge_distance_stroke(bGPDframe *gpf,
BKE_gpencil_dissolve_points(gpf, gps, GP_SPOINT_TAG);
}
}
+
+/* Helper: Check materials with same color. */
+static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Material **r_mat)
+{
+ Material *ma = NULL;
+ float color_cu[4];
+ linearrgb_to_srgb_v3_v3(color_cu, color);
+ float hsv1[4];
+ rgb_to_hsv_v(color_cu, hsv1);
+ hsv1[3] = color[3];
+
+ for (int i = 1; i <= ob_gp->totcol; i++) {
+ ma = give_current_material(ob_gp, i);
+ MaterialGPencilStyle *gp_style = ma->gp_style;
+ /* Check color with small tolerance (better in HSV). */
+ float hsv2[4];
+ rgb_to_hsv_v(gp_style->fill_rgba, hsv2);
+ hsv2[3] = gp_style->fill_rgba[3];
+ if ((gp_style->fill_style == GP_STYLE_FILL_STYLE_SOLID) && (compare_v4v4(hsv1, hsv2, 0.01f))) {
+ *r_mat = ma;
+ return i - 1;
+ }
+ }
+
+ *r_mat = NULL;
+ return -1;
+}
+
+/* Helper: Add gpencil material using curve material as base. */
+static Material *gpencil_add_from_curve_material(Main *bmain,
+ Object *ob_gp,
+ float cu_color[4],
+ const bool gpencil_lines,
+ const bool fill,
+ int *r_idx)
+{
+ Material *mat_gp = BKE_gpencil_object_material_new(
+ bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx);
+ MaterialGPencilStyle *gp_style = mat_gp->gp_style;
+
+ /* Stroke color. */
+ if (gpencil_lines) {
+ ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f);
+ gp_style->flag |= GP_STYLE_STROKE_SHOW;
+ }
+ else {
+ linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color);
+ gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
+ }
+
+ /* Fill color. */
+ linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color);
+ /* Fill is false if the original curve hasn't material assigned, so enable it. */
+ if (fill) {
+ gp_style->flag |= GP_STYLE_FILL_SHOW;
+ }
+
+ /* Check at least one is enabled. */
+ if (((gp_style->flag & GP_STYLE_STROKE_SHOW) == 0) &&
+ ((gp_style->flag & GP_STYLE_FILL_SHOW) == 0)) {
+ gp_style->flag |= GP_STYLE_STROKE_SHOW;
+ }
+
+ return mat_gp;
+}
+
+/* Helper: Create new stroke section. */
+static void gpencil_add_new_points(bGPDstroke *gps,
+ float *coord_array,
+ float pressure,
+ int init,
+ int totpoints,
+ float init_co[3],
+ bool last)
+{
+ for (int i = 0; i < totpoints; i++) {
+ bGPDspoint *pt = &gps->points[i + init];
+ copy_v3_v3(&pt->x, &coord_array[3 * i]);
+ /* Be sure the last point is not on top of the first point of the curve or
+ * the close of the stroke will produce glitches. */
+ if ((last) && (i > 0) && (i == totpoints - 1)) {
+ float dist = len_v3v3(init_co, &pt->x);
+ if (dist < 0.1f) {
+ /* Interpolate between previous point and current to back slightly. */
+ bGPDspoint *pt_prev = &gps->points[i + init - 1];
+ interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f);
+ }
+ }
+
+ pt->pressure = pressure;
+ pt->strength = 1.0f;
+ }
+}
+
+/* Helper: Get the first collection that includes the object. */
+static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob)
+{
+ Collection *mycol = NULL;
+ FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
+ for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
+ if ((mycol == NULL) && (cob->ob == ob)) {
+ mycol = collection;
+ }
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END;
+
+ return mycol;
+}
+
+/* Helper: Convert one spline to grease pencil stroke. */
+static void gpencil_convert_spline(Main *bmain,
+ Object *ob_gp,
+ Object *ob_cu,
+ const bool gpencil_lines,
+ const bool only_stroke,
+ bGPDframe *gpf,
+ Nurb *nu)
+{
+ Curve *cu = (Curve *)ob_cu->data;
+ bool cyclic = true;
+
+ /* Create Stroke. */
+ bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke");
+ gps->thickness = 1.0f;
+ gps->gradient_f = 1.0f;
+ ARRAY_SET_ITEMS(gps->gradient_s, 1.0f, 1.0f);
+ ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND);
+ gps->inittime = 0.0f;
+
+ /* Enable recalculation flag by default. */
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->flag &= ~GP_STROKE_SELECT;
+ gps->flag |= GP_STROKE_3DSPACE;
+
+ gps->mat_nr = 0;
+ /* Count total points
+ * The total of points must consider that last point of each segment is equal to the first
+ * point of next segment.
+ */
+ int totpoints = 0;
+ int segments = 0;
+ int resolu = nu->resolu + 1;
+ segments = nu->pntsu;
+ if (((nu->flagu & CU_NURB_CYCLIC) == 0) || (nu->pntsu == 2)) {
+ segments--;
+ cyclic = false;
+ }
+ totpoints = (resolu * segments) - (segments - 1);
+
+ /* Initialize triangle memory to dummy data. */
+ gps->tot_triangles = 0;
+ gps->triangles = NULL;
+
+ /* Materials
+ * Notice: The color of the material is the color of viewport and not the final shader color.
+ */
+ Material *mat_gp = NULL;
+ bool fill = true;
+ /* Check if grease pencil has a material with same color.*/
+ float color[4];
+ if ((cu->mat) && (*cu->mat)) {
+ Material *mat_cu = *cu->mat;
+ copy_v4_v4(color, &mat_cu->r);
+ }
+ else {
+ /* Gray (unassigned from SVG add-on) */
+ zero_v4(color);
+ add_v3_fl(color, 0.6f);
+ color[3] = 1.0f;
+ fill = false;
+ }
+
+ /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and
+ * there is only one color, the stroke must not be closed, fill to false and use for
+ * stroke the fill color.
+ */
+ bool do_stroke = false;
+ if (ob_cu->totcol == 1) {
+ Material *ma_stroke = give_current_material(ob_cu, 1);
+ if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) {
+ do_stroke = true;
+ }
+ }
+
+ int r_idx = gpencil_check_same_material_color(ob_gp, color, &mat_gp);
+ if ((ob_cu->totcol > 0) && (r_idx < 0)) {
+ Material *mat_curve = give_current_material(ob_cu, 1);
+ mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx);
+
+ if ((mat_curve) && (mat_curve->gp_style != NULL)) {
+ MaterialGPencilStyle *gp_style_cur = mat_curve->gp_style;
+ MaterialGPencilStyle *gp_style_gp = mat_gp->gp_style;
+
+ copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba);
+ gp_style_gp->fill_style = gp_style_cur->fill_style;
+ gp_style_gp->mix_factor = gp_style_cur->mix_factor;
+ gp_style_gp->gradient_angle = gp_style_cur->gradient_angle;
+ }
+
+ /* If object has more than 1 material, use second material for stroke color. */
+ if ((!only_stroke) && (ob_cu->totcol > 1) && (give_current_material(ob_cu, 2))) {
+ mat_curve = give_current_material(ob_cu, 2);
+ linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
+ mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
+ }
+ else if ((only_stroke) || (do_stroke)) {
+ /* Also use the first color if the fill is none for stroke color. */
+ if (ob_cu->totcol > 0) {
+ mat_curve = give_current_material(ob_cu, 1);
+ linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r);
+ mat_gp->gp_style->stroke_rgba[3] = mat_curve->a;
+ /* Set fill and stroke depending of curve type (3D or 2D). */
+ if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) {
+ mat_gp->gp_style->flag |= GP_STYLE_STROKE_SHOW;
+ mat_gp->gp_style->flag &= ~GP_STYLE_FILL_SHOW;
+ }
+ else {
+ mat_gp->gp_style->flag &= ~GP_STYLE_STROKE_SHOW;
+ mat_gp->gp_style->flag |= GP_STYLE_FILL_SHOW;
+ }
+ }
+ }
+ }
+ CLAMP_MIN(r_idx, 0);
+
+ /* Assign material index to stroke. */
+ gps->mat_nr = r_idx;
+
+ /* Add stroke to frame.*/
+ BLI_addtail(&gpf->strokes, gps);
+
+ float *coord_array = NULL;
+ float init_co[3];
+
+ switch (nu->type) {
+ case CU_POLY: {
+ /* Allocate memory for storage points. */
+ gps->totpoints = nu->pntsu;
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ /* Increase thickness for this type. */
+ gps->thickness = 10.0f;
+
+ /* Get all curve points */
+ for (int s = 0; s < gps->totpoints; s++) {
+ BPoint *bp = &nu->bp[s];
+ bGPDspoint *pt = &gps->points[s];
+ copy_v3_v3(&pt->x, bp->vec);
+ pt->pressure = bp->radius;
+ pt->strength = 1.0f;
+ }
+ break;
+ }
+ case CU_BEZIER: {
+ /* Allocate memory for storage points. */
+ gps->totpoints = totpoints;
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+
+ int init = 0;
+ resolu = nu->resolu + 1;
+ segments = nu->pntsu;
+ if (((nu->flagu & CU_NURB_CYCLIC) == 0) || (nu->pntsu == 2)) {
+ segments--;
+ }
+ /* Get all interpolated curve points of Beziert */
+ for (int s = 0; s < segments; s++) {
+ int inext = (s + 1) % nu->pntsu;
+ BezTriple *prevbezt = &nu->bezt[s];
+ BezTriple *bezt = &nu->bezt[inext];
+ bool last = (bool)(s == segments - 1);
+
+ coord_array = MEM_callocN((size_t)3 * resolu * sizeof(float), __func__);
+
+ for (int j = 0; j < 3; j++) {
+ BKE_curve_forward_diff_bezier(prevbezt->vec[1][j],
+ prevbezt->vec[2][j],
+ bezt->vec[0][j],
+ bezt->vec[1][j],
+ coord_array + j,
+ resolu - 1,
+ 3 * sizeof(float));
+ }
+ /* Save first point coordinates. */
+ if (s == 0) {
+ copy_v3_v3(init_co, &coord_array[0]);
+ }
+ /* Add points to the stroke */
+ gpencil_add_new_points(gps, coord_array, bezt->radius, init, resolu, init_co, last);
+ /* Free memory. */
+ MEM_SAFE_FREE(coord_array);
+
+ /* As the last point of segment is the first point of next segment, back one array
+ * element to avoid duplicated points on the same location.
+ */
+ init += resolu - 1;
+ }
+ break;
+ }
+ case CU_NURBS: {
+ if (nu->pntsv == 1) {
+
+ int nurb_points;
+ if (nu->flagu & CU_NURB_CYCLIC) {
+ resolu++;
+ nurb_points = nu->pntsu * resolu;
+ }
+ else {
+ nurb_points = (nu->pntsu - 1) * resolu;
+ }
+ /* Get all curve points. */
+ coord_array = MEM_callocN(sizeof(float[3]) * nurb_points, __func__);
+ BKE_nurb_makeCurve(nu, coord_array, NULL, NULL, NULL, resolu, sizeof(float[3]));
+
+ /* Allocate memory for storage points. */
+ gps->totpoints = nurb_points - 1;
+ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+
+ /* Add points. */
+ gpencil_add_new_points(gps, coord_array, 1.0f, 0, gps->totpoints, init_co, false);
+
+ MEM_SAFE_FREE(coord_array);
+ }
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ /* Cyclic curve, close stroke. */
+ if ((cyclic) && (!do_stroke)) {
+ BKE_gpencil_close_stroke(gps);
+ }
+}
+
+/* Convert a curve object to grease pencil stroke.
+ *
+ * \param bmain: Main thread pointer
+ * \param scene: Original scene.
+ * \param ob_gp: Grease pencil object to add strokes.
+ * \param ob_cu: Curve to convert.
+ * \param gpencil_lines: Use lines for strokes.
+ * \param use_collections: Create layers using collection names.
+ * \param only_stroke: The material must be only stroke without fill.
+ */
+void BKE_gpencil_convert_curve(Main *bmain,
+ Scene *scene,
+ Object *ob_gp,
+ Object *ob_cu,
+ const bool gpencil_lines,
+ const bool use_collections,
+ const bool only_stroke)
+{
+ if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) {
+ return;
+ }
+
+ Curve *cu = (Curve *)ob_cu->data;
+ bGPdata *gpd = (bGPdata *)ob_gp->data;
+ bGPDlayer *gpl = NULL;
+
+ /* If the curve is empty, cancel. */
+ if (cu->nurb.first == NULL) {
+ return;
+ }
+
+ /* Check if there is an active layer. */
+ if (use_collections) {
+ Collection *collection = gpencil_get_parent_collection(scene, ob_cu);
+ if (collection != NULL) {
+ gpl = BLI_findstring(&gpd->layers, collection->id.name + 2, offsetof(bGPDlayer, info));
+ if (gpl == NULL) {
+ gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true);
+ }
+ }
+ }
+
+ if (gpl == NULL) {
+ gpl = BKE_gpencil_layer_getactive(gpd);
+ if (gpl == NULL) {
+ gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
+ }
+ }
+
+ /* Check if there is an active frame and add if needed. */
+ bGPDframe *gpf = BKE_gpencil_layer_getframe(gpl, CFRA, GP_GETFRAME_ADD_COPY);
+
+ /* Read all splines of the curve and create a stroke for each. */
+ for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) {
+ gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, only_stroke, gpf, nu);
+ }
+
+ /* Tag for recalculation */
+ DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE);
+}
diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c
index 36d2d6316f7..1750a389788 100644
--- a/source/blender/blenkernel/intern/gpencil_modifier.c
+++ b/source/blender/blenkernel/intern/gpencil_modifier.c
@@ -779,26 +779,28 @@ void BKE_gpencil_subdivide(bGPDstroke *gps, int level, int flag)
}
/* Copy frame but do not assign new memory */
-static void gpencil_copy_frame(Object *ob, bGPDframe *gpf, bGPDframe *derived_gpf)
+static void gpencil_frame_copy_noalloc(Object *ob, bGPDframe *gpf, bGPDframe *gpf_eval)
{
- derived_gpf->prev = gpf->prev;
- derived_gpf->next = gpf->next;
- derived_gpf->framenum = gpf->framenum;
- derived_gpf->flag = gpf->flag;
- derived_gpf->key_type = gpf->key_type;
- derived_gpf->runtime = gpf->runtime;
- copy_m4_m4(derived_gpf->runtime.parent_obmat, gpf->runtime.parent_obmat);
+ gpf_eval->prev = gpf->prev;
+ gpf_eval->next = gpf->next;
+ gpf_eval->framenum = gpf->framenum;
+ gpf_eval->flag = gpf->flag;
+ gpf_eval->key_type = gpf->key_type;
+ gpf_eval->runtime = gpf->runtime;
+ copy_m4_m4(gpf_eval->runtime.parent_obmat, gpf->runtime.parent_obmat);
/* copy strokes */
- BLI_listbase_clear(&derived_gpf->strokes);
+ BLI_listbase_clear(&gpf_eval->strokes);
for (bGPDstroke *gps_src = gpf->strokes.first; gps_src; gps_src = gps_src->next) {
/* make copy of source stroke */
bGPDstroke *gps_dst = BKE_gpencil_stroke_duplicate(gps_src);
/* copy color to temp fields to apply temporal changes in the stroke */
MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps_src->mat_nr + 1);
- copy_v4_v4(gps_dst->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
- copy_v4_v4(gps_dst->runtime.tmp_fill_rgba, gp_style->fill_rgba);
+ if (gp_style) {
+ copy_v4_v4(gps_dst->runtime.tmp_stroke_rgba, gp_style->stroke_rgba);
+ copy_v4_v4(gps_dst->runtime.tmp_fill_rgba, gp_style->fill_rgba);
+ }
/* Save original pointers for using in edit and select operators. */
gps_dst->runtime.gps_orig = gps_src;
@@ -808,25 +810,27 @@ static void gpencil_copy_frame(Object *ob, bGPDframe *gpf, bGPDframe *derived_gp
pt_dst->runtime.idx_orig = i;
}
- BLI_addtail(&derived_gpf->strokes, gps_dst);
+ BLI_addtail(&gpf_eval->strokes, gps_dst);
}
}
-/* Ensure there is a derived frame */
-static void gpencil_ensure_derived_frame(
- int idx, Object *ob, bGPDlayer *gpl, bGPDframe *gpf, bGPDframe **derived_gpf)
+/* Ensure there is a evaluated frame */
+static void gpencil_evaluated_frame_ensure(int idx,
+ Object *ob,
+ bGPDframe *gpf,
+ bGPDframe **gpf_eval)
{
- /* create derived frames array data or expand */
- bGPDframe *derived_frames = ob->runtime.derived_frames;
- *derived_gpf = &derived_frames[idx];
+ /* Create evaluated frames array data or expand. */
+ bGPDframe *evaluated_frames = ob->runtime.gpencil_evaluated_frames;
+ *gpf_eval = &evaluated_frames[idx];
- /* if derived frame create a new one */
- if (*derived_gpf != NULL) {
+ /* If already exist a evaluated frame create a new one. */
+ if (*gpf_eval != NULL) {
/* first clear temp data */
- BKE_gpencil_free_frame_runtime_data(*derived_gpf);
+ BKE_gpencil_free_frame_runtime_data(*gpf_eval);
}
- /* copy data (do not assign new memory)*/
- gpencil_copy_frame(ob, gpf, *derived_gpf);
+ /* Copy data (do not assign new memory). */
+ gpencil_frame_copy_noalloc(ob, gpf, *gpf_eval);
}
/* Calculate gpencil modifiers */
@@ -836,21 +840,22 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
Object *ob_orig = DEG_get_original_object(ob);
bGPdata *gpd = (bGPdata *)ob_orig->data;
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
- const bool simplify_modif = GP_SIMPLIFY_MODIF(scene, false);
+ const bool simplify_modif = GPENCIL_SIMPLIFY_MODIF(scene, false);
const bool is_render = (bool)(DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
int cfra_eval = (int)DEG_get_ctime(depsgraph);
- /* Create array of derived frames equal to number of layers. */
- ob->runtime.tot_layers = BLI_listbase_count(&gpd->layers);
- CLAMP_MIN(ob->runtime.tot_layers, 1);
- if (ob->runtime.derived_frames == NULL) {
- ob->runtime.derived_frames = MEM_callocN(sizeof(struct bGPDframe) * ob->runtime.tot_layers,
- __func__);
+ /* Create array of evaluated frames equal to number of layers. */
+ ob->runtime.gpencil_tot_layers = BLI_listbase_count(&gpd->layers);
+ CLAMP_MIN(ob->runtime.gpencil_tot_layers, 1);
+ if (ob->runtime.gpencil_evaluated_frames == NULL) {
+ ob->runtime.gpencil_evaluated_frames = MEM_callocN(
+ sizeof(struct bGPDframe) * ob->runtime.gpencil_tot_layers, __func__);
}
else {
- ob->runtime.derived_frames = MEM_recallocN(ob->runtime.derived_frames,
- sizeof(struct bGPDframe) * ob->runtime.tot_layers);
+ ob->runtime.gpencil_evaluated_frames = MEM_recallocN(ob->runtime.gpencil_evaluated_frames,
+ sizeof(struct bGPDframe) *
+ ob->runtime.gpencil_tot_layers);
}
/* Init general modifiers data. */
@@ -877,8 +882,8 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
}
/* Create a duplicate data set of stroke to modify. */
- bGPDframe *derived_gpf = NULL;
- gpencil_ensure_derived_frame(idx, ob, gpl, gpf, &derived_gpf);
+ bGPDframe *gpf_eval = NULL;
+ gpencil_evaluated_frame_ensure(idx, ob, gpf, &gpf_eval);
/* Skip all if some disable flag is enabled. */
if ((ob->greasepencil_modifiers.first == NULL) || (is_multiedit) || (simplify_modif)) {
@@ -888,13 +893,13 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
/* Apply geometry modifiers (create new geometry). */
if (BKE_gpencil_has_geometry_modifiers(ob)) {
- BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, derived_gpf, is_render);
+ BKE_gpencil_geometry_modifiers(depsgraph, ob, gpl, gpf_eval, is_render);
}
/* Loop all strokes and deform them. */
- for (bGPDstroke *gps = derived_gpf->strokes.first; gps; gps = gps->next) {
+ for (bGPDstroke *gps = gpf_eval->strokes.first; gps; gps = gps->next) {
/* Apply modifiers that only deform geometry */
- BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, derived_gpf, gps, is_render);
+ BKE_gpencil_stroke_modifiers(depsgraph, ob, gpl, gpf_eval, gps, is_render);
}
idx++;
diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c
index 61de6a8c06a..9a38f348361 100644
--- a/source/blender/blenkernel/intern/key.c
+++ b/source/blender/blenkernel/intern/key.c
@@ -2066,9 +2066,9 @@ void BKE_keyblock_mesh_calc_normals(struct KeyBlock *kb,
}
/************************* raw coords ************************/
-void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3])
+void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
{
- float(*co)[3] = vertCos;
+ const float(*co)[3] = vertCos;
float *fp = kb->data;
int tot, a;
@@ -2126,7 +2126,7 @@ void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)
}
}
-void BKE_keyblock_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3])
+void BKE_keyblock_convert_from_vertcos(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
{
int tot = 0, elemsize;
@@ -2219,7 +2219,7 @@ float (*BKE_keyblock_convert_to_vertcos(Object *ob, KeyBlock *kb))[3]
}
/************************* raw coord offsets ************************/
-void BKE_keyblock_update_from_offset(Object *ob, KeyBlock *kb, float (*ofs)[3])
+void BKE_keyblock_update_from_offset(Object *ob, KeyBlock *kb, const float (*ofs)[3])
{
int a;
float *fp = kb->data;
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index 83b354ffb4a..e46b7ca5130 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -139,7 +139,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
BPoint *bp;
int i, u, v, w;
float fu, fv, fw, uc, vc, wc, du = 0.0, dv = 0.0, dw = 0.0;
- float *co, (*vertexCos)[3] = NULL;
+ float *co, (*vert_coords)[3] = NULL;
/* vertex weight groups are just freed all for now */
if (lt->dvert) {
@@ -159,7 +159,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
}
}
- vertexCos = MEM_mallocN(sizeof(*vertexCos) * uNew * vNew * wNew, "tmp_vcos");
+ vert_coords = MEM_mallocN(sizeof(*vert_coords) * uNew * vNew * wNew, "tmp_vcos");
calc_lat_fudu(lt->flag, uNew, &fu, &du);
calc_lat_fudu(lt->flag, vNew, &fv, &dv);
@@ -187,7 +187,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
}
}
- co = vertexCos[0];
+ co = vert_coords[0];
for (w = 0, wc = fw; w < wNew; w++, wc += dw) {
for (v = 0, vc = fv; v < vNew; v++, vc += dv) {
for (u = 0, uc = fu; u < uNew; u++, co += 3, uc += du) {
@@ -212,7 +212,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
copy_m4_m4(mat, ltOb->obmat);
unit_m4(ltOb->obmat);
- lattice_deform_verts(ltOb, NULL, NULL, vertexCos, uNew * vNew * wNew, NULL, 1.0f);
+ lattice_deform_verts(ltOb, NULL, NULL, vert_coords, uNew * vNew * wNew, NULL, 1.0f);
copy_m4_m4(ltOb->obmat, mat);
lt->typeu = typeu;
@@ -238,10 +238,10 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb)
bp = lt->def;
for (i = 0; i < lt->pntsu * lt->pntsv * lt->pntsw; i++, bp++) {
- copy_v3_v3(bp->vec, vertexCos[i]);
+ copy_v3_v3(bp->vec, vert_coords[i]);
}
- MEM_freeN(vertexCos);
+ MEM_freeN(vert_coords);
}
void BKE_lattice_init(Lattice *lt)
@@ -747,7 +747,7 @@ static bool calc_curve_deform(
void curve_deform_verts(Object *cuOb,
Object *target,
- float (*vertexCos)[3],
+ float (*vert_coords)[3],
int numVerts,
MDeformVert *dvert,
const int defgrp_index,
@@ -786,11 +786,11 @@ void curve_deform_verts(Object *cuOb,
const float weight = defvert_find_weight(dvert_iter, defgrp_index);
if (weight > 0.0f) {
- mul_m4_v3(cd.curvespace, vertexCos[a]);
- copy_v3_v3(vec, vertexCos[a]);
+ mul_m4_v3(cd.curvespace, vert_coords[a]);
+ copy_v3_v3(vec, vert_coords[a]);
calc_curve_deform(cuOb, vec, defaxis, &cd, NULL);
- interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
- mul_m4_v3(cd.objectspace, vertexCos[a]);
+ interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight);
+ mul_m4_v3(cd.objectspace, vert_coords[a]);
}
}
}
@@ -800,8 +800,8 @@ void curve_deform_verts(Object *cuOb,
for (a = 0, dvert_iter = dvert; a < numVerts; a++, dvert_iter++) {
if (defvert_find_weight(dvert_iter, defgrp_index) > 0.0f) {
- mul_m4_v3(cd.curvespace, vertexCos[a]);
- minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]);
+ mul_m4_v3(cd.curvespace, vert_coords[a]);
+ minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]);
}
}
@@ -810,10 +810,10 @@ void curve_deform_verts(Object *cuOb,
if (weight > 0.0f) {
/* already in 'cd.curvespace', prev for loop */
- copy_v3_v3(vec, vertexCos[a]);
+ copy_v3_v3(vec, vert_coords[a]);
calc_curve_deform(cuOb, vec, defaxis, &cd, NULL);
- interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
- mul_m4_v3(cd.objectspace, vertexCos[a]);
+ interp_v3_v3v3(vert_coords[a], vert_coords[a], vec, weight);
+ mul_m4_v3(cd.objectspace, vert_coords[a]);
}
}
}
@@ -821,9 +821,9 @@ void curve_deform_verts(Object *cuOb,
else {
if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
for (a = 0; a < numVerts; a++) {
- mul_m4_v3(cd.curvespace, vertexCos[a]);
- calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL);
- mul_m4_v3(cd.objectspace, vertexCos[a]);
+ mul_m4_v3(cd.curvespace, vert_coords[a]);
+ calc_curve_deform(cuOb, vert_coords[a], defaxis, &cd, NULL);
+ mul_m4_v3(cd.objectspace, vert_coords[a]);
}
}
else {
@@ -831,14 +831,14 @@ void curve_deform_verts(Object *cuOb,
INIT_MINMAX(cd.dmin, cd.dmax);
for (a = 0; a < numVerts; a++) {
- mul_m4_v3(cd.curvespace, vertexCos[a]);
- minmax_v3v3_v3(cd.dmin, cd.dmax, vertexCos[a]);
+ mul_m4_v3(cd.curvespace, vert_coords[a]);
+ minmax_v3v3_v3(cd.dmin, cd.dmax, vert_coords[a]);
}
for (a = 0; a < numVerts; a++) {
/* already in 'cd.curvespace', prev for loop */
- calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL);
- mul_m4_v3(cd.objectspace, vertexCos[a]);
+ calc_curve_deform(cuOb, vert_coords[a], defaxis, &cd, NULL);
+ mul_m4_v3(cd.objectspace, vert_coords[a]);
}
}
}
@@ -881,7 +881,7 @@ void curve_deform_vector(
typedef struct LatticeDeformUserdata {
LatticeDeformData *lattice_deform_data;
- float (*vertexCos)[3];
+ float (*vert_coords)[3];
MDeformVert *dvert;
int defgrp_index;
float fac;
@@ -896,18 +896,18 @@ static void lattice_deform_vert_task(void *__restrict userdata,
if (data->dvert != NULL) {
const float weight = defvert_find_weight(data->dvert + index, data->defgrp_index);
if (weight > 0.0f) {
- calc_latt_deform(data->lattice_deform_data, data->vertexCos[index], weight * data->fac);
+ calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], weight * data->fac);
}
}
else {
- calc_latt_deform(data->lattice_deform_data, data->vertexCos[index], data->fac);
+ calc_latt_deform(data->lattice_deform_data, data->vert_coords[index], data->fac);
}
}
void lattice_deform_verts(Object *laOb,
Object *target,
Mesh *mesh,
- float (*vertexCos)[3],
+ float (*vert_coords)[3],
int numVerts,
const char *vgroup,
float fac)
@@ -942,11 +942,13 @@ void lattice_deform_verts(Object *laOb,
}
}
- LatticeDeformUserdata data = {.lattice_deform_data = lattice_deform_data,
- .vertexCos = vertexCos,
- .dvert = dvert,
- .defgrp_index = defgrp_index,
- .fac = fac};
+ LatticeDeformUserdata data = {
+ .lattice_deform_data = lattice_deform_data,
+ .vert_coords = vert_coords,
+ .dvert = dvert,
+ .defgrp_index = defgrp_index,
+ .fac = fac,
+ };
TaskParallelSettings settings;
BLI_parallel_range_settings_defaults(&settings);
@@ -1055,33 +1057,37 @@ void outside_lattice(Lattice *lt)
}
}
-float (*BKE_lattice_vertexcos_get(struct Object *ob, int *r_numVerts))[3]
+void BKE_lattice_vert_coords_get(const Lattice *lt, float (*vert_coords)[3])
{
- Lattice *lt = ob->data;
- int i, numVerts;
- float(*vertexCos)[3];
-
- if (lt->editlatt) {
- lt = lt->editlatt->latt;
+ const int vert_len = lt->pntsu * lt->pntsv * lt->pntsw;
+ for (int i = 0; i < vert_len; i++) {
+ copy_v3_v3(vert_coords[i], lt->def[i].vec);
}
- numVerts = *r_numVerts = lt->pntsu * lt->pntsv * lt->pntsw;
+}
- vertexCos = MEM_mallocN(sizeof(*vertexCos) * numVerts, "lt_vcos");
+float (*BKE_lattice_vert_coords_alloc(const Lattice *lt, int *r_vert_len))[3]
+{
+ const int vert_len = *r_vert_len = lt->pntsu * lt->pntsv * lt->pntsw;
+ float(*vert_coords)[3] = MEM_mallocN(sizeof(*vert_coords) * vert_len, __func__);
+ BKE_lattice_vert_coords_get(lt, vert_coords);
+ return vert_coords;
+}
+void BKE_lattice_vert_coords_apply_with_mat4(struct Lattice *lt,
+ const float (*vertexCos)[3],
+ const float mat[4][4])
+{
+ int i, numVerts = lt->pntsu * lt->pntsv * lt->pntsw;
for (i = 0; i < numVerts; i++) {
- copy_v3_v3(vertexCos[i], lt->def[i].vec);
+ mul_v3_m4v3(lt->def[i].vec, mat, vertexCos[i]);
}
-
- return vertexCos;
}
-void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3])
+void BKE_lattice_vert_coords_apply(Lattice *lt, const float (*vert_coords)[3])
{
- Lattice *lt = ob->data;
- int i, numVerts = lt->pntsu * lt->pntsv * lt->pntsw;
-
- for (i = 0; i < numVerts; i++) {
- copy_v3_v3(lt->def[i].vec, vertexCos[i]);
+ const int vert_len = lt->pntsu * lt->pntsv * lt->pntsw;
+ for (int i = 0; i < vert_len; i++) {
+ copy_v3_v3(lt->def[i].vec, vert_coords[i]);
}
}
@@ -1093,7 +1099,7 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec
Object *ob_orig = DEG_get_original_object(ob);
VirtualModifierData virtualModifierData;
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
- float(*vertexCos)[3] = NULL;
+ float(*vert_coords)[3] = NULL;
int numVerts, editmode = (lt->editlatt != NULL);
const ModifierEvalContext mectx = {depsgraph, ob, 0};
@@ -1123,29 +1129,37 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec
continue;
}
- if (!vertexCos) {
- vertexCos = BKE_lattice_vertexcos_get(ob_orig, &numVerts);
+ if (!vert_coords) {
+ Lattice *lt_orig = ob_orig->data;
+ if (lt_orig->editlatt) {
+ lt_orig = lt_orig->editlatt->latt;
+ }
+ vert_coords = BKE_lattice_vert_coords_alloc(lt_orig, &numVerts);
}
- mti->deformVerts(md, &mectx, NULL, vertexCos, numVerts);
+ mti->deformVerts(md, &mectx, NULL, vert_coords, numVerts);
}
if (ob->id.tag & LIB_TAG_COPIED_ON_WRITE) {
- if (vertexCos) {
- BKE_lattice_vertexcos_apply(ob, vertexCos);
- MEM_freeN(vertexCos);
+ if (vert_coords) {
+ BKE_lattice_vert_coords_apply(ob->data, vert_coords);
+ MEM_freeN(vert_coords);
}
}
else {
/* Displist won't do anything; this is just for posterity's sake until we remove it. */
- if (!vertexCos) {
- vertexCos = BKE_lattice_vertexcos_get(ob_orig, &numVerts);
+ if (!vert_coords) {
+ Lattice *lt_orig = ob_orig->data;
+ if (lt_orig->editlatt) {
+ lt_orig = lt_orig->editlatt->latt;
+ }
+ vert_coords = BKE_lattice_vert_coords_alloc(lt_orig, &numVerts);
}
DispList *dl = MEM_callocN(sizeof(*dl), "lt_dl");
dl->type = DL_VERTS;
dl->parts = 1;
dl->nr = numVerts;
- dl->verts = (float *)vertexCos;
+ dl->verts = (float *)vert_coords;
BLI_addtail(&ob->runtime.curve_cache->disp, dl);
}
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 40608285785..de105b9b62a 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -494,6 +494,36 @@ static LayerCollection *collection_from_index(ListBase *lb, const int number, in
}
/**
+ * Determine if a collection is hidden, viewport visibility restricted, or excluded
+ */
+static bool layer_collection_hidden(ViewLayer *view_layer, LayerCollection *lc)
+{
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ return true;
+ }
+
+ /* Check visiblilty restriction flags */
+ if (lc->flag & LAYER_COLLECTION_HIDE || lc->collection->flag & COLLECTION_RESTRICT_VIEWPORT) {
+ return true;
+ }
+ else {
+ /* Restriction flags stay set, so we need to check parents */
+ CollectionParent *parent = lc->collection->parents.first;
+
+ if (parent) {
+ lc = BKE_layer_collection_first_from_scene_collection(view_layer, parent->collection);
+
+ return lc && layer_collection_hidden(view_layer, lc);
+ }
+ else {
+ return false;
+ }
+ }
+
+ return false;
+}
+
+/**
* Get the collection for a given index
*/
LayerCollection *BKE_layer_collection_from_index(ViewLayer *view_layer, const int index)
@@ -537,8 +567,9 @@ LayerCollection *BKE_layer_collection_activate_parent(ViewLayer *view_layer, Lay
lc = NULL;
}
- if (lc && (lc->flag & LAYER_COLLECTION_EXCLUDE)) {
- /* Don't activate excluded collections. */
+ /* Don't activate excluded or hidden collections to prevent creating objects in a hidden
+ * collection from the UI */
+ if (lc && layer_collection_hidden(view_layer, lc)) {
return BKE_layer_collection_activate_parent(view_layer, lc);
}
@@ -817,8 +848,7 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
/* Always set a valid active collection. */
LayerCollection *active = view_layer->active_collection;
-
- if (active && (active->flag & LAYER_COLLECTION_EXCLUDE)) {
+ if (active && layer_collection_hidden(view_layer, active)) {
BKE_layer_collection_activate_parent(view_layer, active);
}
else if (active == NULL) {
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index de6f5142a19..f45eba2b53f 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -851,8 +851,8 @@ void BKE_id_swap(Main *bmain, ID *id_a, ID *id_b)
id_b->properties = id_a_back.properties;
/* Swap will have broken internal references to itself, restore them. */
- BKE_libblock_relink_ex(bmain, id_a, id_b, id_a, false);
- BKE_libblock_relink_ex(bmain, id_b, id_a, id_b, false);
+ BKE_libblock_relink_ex(bmain, id_a, id_b, id_a, ID_REMAP_SKIP_NEVER_NULL_USAGE);
+ BKE_libblock_relink_ex(bmain, id_b, id_a, id_b, ID_REMAP_SKIP_NEVER_NULL_USAGE);
}
/** Does *not* set ID->newid pointer. */
@@ -1408,21 +1408,24 @@ void *BKE_id_new_nomain(const short type, const char *name)
return id;
}
-void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag)
+void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, int flag)
{
ID *new_id = *r_newid;
- /* Grrrrrrrrr... Not adding 'root' nodetrees to bmain.... grrrrrrrrrrrrrrrrrrrr! */
- /* This is taken from original ntree copy code, might be weak actually? */
- const bool use_nodetree_alloc_exception = ((GS(id->name) == ID_NT) && (bmain != NULL) &&
- (BLI_findindex(&bmain->nodetrees, id) < 0));
-
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || bmain != NULL);
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) != 0 || (flag & LIB_ID_CREATE_NO_ALLOCATE) == 0);
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) != 0);
/* Never implicitly copy shapekeys when generating temp data outside of Main database. */
BLI_assert((flag & LIB_ID_CREATE_NO_MAIN) == 0 || (flag & LIB_ID_COPY_SHAPEKEY) == 0);
+ /* 'Private ID' data handling. */
+ if ((bmain != NULL) && (id->flag & LIB_PRIVATE_DATA) != 0) {
+ flag |= LIB_ID_CREATE_NO_MAIN;
+ }
+
+ /* The id->flag bits to copy over. */
+ const int copy_flag_mask = LIB_PRIVATE_DATA;
+
if ((flag & LIB_ID_CREATE_NO_ALLOCATE) != 0) {
/* r_newid already contains pointer to allocated memory. */
/* TODO do we want to memset(0) whole mem before filling it? */
@@ -1432,10 +1435,7 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla
/* TODO Do we want/need to copy more from ID struct itself? */
}
else {
- new_id = BKE_libblock_alloc(bmain,
- GS(id->name),
- id->name + 2,
- flag | (use_nodetree_alloc_exception ? LIB_ID_CREATE_NO_MAIN : 0));
+ new_id = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2, flag);
}
BLI_assert(new_id != NULL);
@@ -1448,6 +1448,8 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla
memcpy(cpn + id_offset, cp + id_offset, id_len - id_offset);
}
+ new_id->flag = (new_id->flag & ~copy_flag_mask) | (id->flag & copy_flag_mask);
+
if (id->properties) {
new_id->properties = IDP_CopyProperty_ex(id->properties, flag);
}
@@ -1727,8 +1729,8 @@ bool BKE_id_new_name_validate(ListBase *lb, ID *id, const char *tname)
/* This was in 2.43 and previous releases
* however all data in blender should be sorted, not just duplicate names
- * sorting should not hurt, but noting just incase it alters the way other
- * functions work, so sort every time */
+ * sorting should not hurt, but noting just in case it alters the way other
+ * functions work, so sort every time. */
#if 0
if (result) {
id_sort_by_name(lb, id);
diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/library_override.c
index e435f07e38d..6532fce5778 100644
--- a/source/blender/blenkernel/intern/library_override.c
+++ b/source/blender/blenkernel/intern/library_override.c
@@ -111,11 +111,11 @@ void BKE_override_library_copy(ID *dst_id, const ID *src_id)
if (dst_id->override_library != NULL) {
if (src_id->override_library == NULL) {
- BKE_override_library_free(&dst_id->override_library);
+ BKE_override_library_free(&dst_id->override_library, true);
return;
}
else {
- BKE_override_library_clear(dst_id->override_library);
+ BKE_override_library_clear(dst_id->override_library, true);
}
}
else if (src_id->override_library == NULL) {
@@ -144,7 +144,7 @@ void BKE_override_library_copy(ID *dst_id, const ID *src_id)
}
/** Clear any overriding data from given \a override. */
-void BKE_override_library_clear(IDOverrideLibrary *override)
+void BKE_override_library_clear(IDOverrideLibrary *override, const bool do_id_user)
{
BLI_assert(override != NULL);
@@ -153,16 +153,18 @@ void BKE_override_library_clear(IDOverrideLibrary *override)
}
BLI_freelistN(&override->properties);
- id_us_min(override->reference);
- /* override->storage should never be refcounted... */
+ if (do_id_user) {
+ id_us_min(override->reference);
+ /* override->storage should never be refcounted... */
+ }
}
/** Free given \a override. */
-void BKE_override_library_free(struct IDOverrideLibrary **override)
+void BKE_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user)
{
BLI_assert(*override != NULL);
- BKE_override_library_clear(*override);
+ BKE_override_library_clear(*override, do_id_user);
MEM_freeN(*override);
*override = NULL;
}
@@ -205,6 +207,11 @@ ID *BKE_override_library_create_from_id(Main *bmain, ID *reference_id)
* \note Set id->newid of overridden libs with newly created overrides,
* caller is responsible to clean those pointers before/after usage as needed.
*
+ * \note By default, it will only remap newly created local overriding data-blocks between
+ * themselves, to avoid 'enforcing' those overrides into all other usages of the linked data in
+ * main. You can add more local IDs to be remapped to use new overriding ones by setting their
+ * LIB_TAG_DOIT tag.
+ *
* \return \a true on success, \a false otherwise.
*/
bool BKE_override_library_create_from_tag(Main *bmain)
@@ -212,26 +219,59 @@ bool BKE_override_library_create_from_tag(Main *bmain)
ID *reference_id;
bool ret = true;
+ ListBase todo_ids = {NULL};
+ LinkData *todo_id_iter;
+
+ /* Get all IDs we want to override. */
FOREACH_MAIN_ID_BEGIN (bmain, reference_id) {
if ((reference_id->tag & LIB_TAG_DOIT) != 0 && reference_id->lib != NULL) {
- if ((reference_id->newid = override_library_create_from(bmain, reference_id)) == NULL) {
- ret = false;
- }
+ todo_id_iter = MEM_callocN(sizeof(*todo_id_iter), __func__);
+ todo_id_iter->data = reference_id;
+ BLI_addtail(&todo_ids, todo_id_iter);
}
}
FOREACH_MAIN_ID_END;
- FOREACH_MAIN_ID_BEGIN (bmain, reference_id) {
- if ((reference_id->tag & LIB_TAG_DOIT) != 0 && reference_id->lib != NULL &&
- reference_id->newid != NULL) {
- ID *local_id = reference_id->newid;
- BKE_libblock_remap(bmain,
- reference_id,
- local_id,
- ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY);
+ /* Override the IDs. */
+ for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) {
+ reference_id = todo_id_iter->data;
+ if ((reference_id->newid = override_library_create_from(bmain, reference_id)) == NULL) {
+ ret = false;
+ }
+ else {
+ /* We also tag the new IDs so that in next step we can remap their pointers too. */
+ reference_id->newid->tag |= LIB_TAG_DOIT;
}
}
- FOREACH_MAIN_ID_END;
+
+ /* Only remap new local ID's pointers, we don't want to force our new overrides onto our whole
+ * existing linked IDs usages. */
+ for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) {
+ ID *other_id;
+ reference_id = todo_id_iter->data;
+
+ if (reference_id->newid == NULL) {
+ continue;
+ }
+
+ /* Still checking the whole Main, that way we can tag other local IDs as needing to be remapped
+ * to use newly created overriding IDs, if needed. */
+ FOREACH_MAIN_ID_BEGIN (bmain, other_id) {
+ if ((other_id->tag & LIB_TAG_DOIT) != 0 && other_id->lib == NULL) {
+ ID *local_id = reference_id->newid;
+ /* Note that using ID_REMAP_SKIP_INDIRECT_USAGE below is superfluous, as we only remap
+ * local IDs usages anyway... */
+ BKE_libblock_relink_ex(bmain,
+ other_id,
+ reference_id,
+ local_id,
+ ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_OVERRIDE_LIBRARY);
+ }
+ }
+ FOREACH_MAIN_ID_END;
+ }
+
+ BLI_freelistN(&todo_ids);
return ret;
}
@@ -628,7 +668,7 @@ void BKE_main_override_library_operations_create(Main *bmain, const bool force_a
ID *id;
FOREACH_MAIN_ID_BEGIN (bmain, id) {
- if (force_auto ||
+ if ((ID_IS_OVERRIDE_LIBRARY(id) && force_auto) ||
(ID_IS_OVERRIDE_LIBRARY_AUTO(id) && (id->tag & LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH))) {
BKE_override_library_operations_create(bmain, id, force_auto);
id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH;
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 8fe2552c03f..61f506a8a6c 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -652,12 +652,11 @@ void BKE_libblock_unlink(Main *bmain,
* ... sigh
*/
void BKE_libblock_relink_ex(
- Main *bmain, void *idv, void *old_idv, void *new_idv, const bool us_min_never_null)
+ Main *bmain, void *idv, void *old_idv, void *new_idv, const short remap_flags)
{
ID *id = idv;
ID *old_id = old_idv;
ID *new_id = new_idv;
- int remap_flags = us_min_never_null ? 0 : ID_REMAP_SKIP_NEVER_NULL_USAGE;
/* No need to lock here, we are only affecting given ID, not bmain database. */
@@ -757,7 +756,7 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user)
}
if (id->override_library) {
- BKE_override_library_free(&id->override_library);
+ BKE_override_library_free(&id->override_library, do_id_user);
}
/* XXX TODO remove animdata handling from each type's freeing func,
@@ -945,7 +944,7 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i
#endif
if ((flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0) {
- BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
+ BKE_libblock_relink_ex(bmain, id, NULL, NULL, 0);
}
BKE_libblock_free_datablock(id, flag);
@@ -1091,7 +1090,7 @@ static void id_delete(Main *bmain, const bool do_tagged_deletion)
bmain, id, NULL, ID_REMAP_FLAG_NEVER_NULL_USAGE | ID_REMAP_FORCE_NEVER_NULL_USAGE);
/* Since we removed ID from Main,
* we also need to unlink its own other IDs usages ourself. */
- BKE_libblock_relink_ex(bmain, id, NULL, NULL, true);
+ BKE_libblock_relink_ex(bmain, id, NULL, NULL, 0);
/* Now we can safely mark that ID as not being in Main database anymore. */
id->tag |= LIB_TAG_NO_MAIN;
/* This is needed because we may not have remapped usages
diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c
index 75c9e0e42a5..07ec8d70af1 100644
--- a/source/blender/blenkernel/intern/light.c
+++ b/source/blender/blenkernel/intern/light.c
@@ -108,12 +108,15 @@ Light *BKE_light_add(Main *bmain, const char *name)
*/
void BKE_light_copy_data(Main *bmain, Light *la_dst, const Light *la_src, const int flag)
{
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+ /* We always need allocation of our private ID data. */
+ const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE;
+
la_dst->curfalloff = BKE_curvemapping_copy(la_src->curfalloff);
if (la_src->nodetree) {
- /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level
- * (see BKE_libblock_copy_ex()). */
- BKE_id_copy_ex(bmain, (ID *)la_src->nodetree, (ID **)&la_dst->nodetree, flag);
+ BKE_id_copy_ex(bmain, (ID *)la_src->nodetree, (ID **)&la_dst->nodetree, flag_private_id_data);
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 7bfe5a7c8ff..e5fa5ff08b0 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -167,6 +167,8 @@ void BKE_linestyle_copy_data(struct Main *bmain,
{
/* We never handle usercount here for own data. */
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+ /* We always need allocation of our private ID data. */
+ const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE;
for (int a = 0; a < MAX_MTEX; a++) {
if (linestyle_src->mtex[a]) {
@@ -176,9 +178,10 @@ void BKE_linestyle_copy_data(struct Main *bmain,
}
if (linestyle_src->nodetree) {
- /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level
- * (see BKE_libblock_copy_ex()). */
- BKE_id_copy_ex(bmain, (ID *)linestyle_src->nodetree, (ID **)&linestyle_dst->nodetree, flag);
+ BKE_id_copy_ex(bmain,
+ (ID *)linestyle_src->nodetree,
+ (ID **)&linestyle_dst->nodetree,
+ flag_private_id_data);
}
LineStyleModifier *m;
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index b6d61563fe8..fc087ff91b2 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -1628,7 +1628,9 @@ MaskLayerShape *BKE_mask_layer_shape_find_frame(MaskLayer *masklay, const int fr
return NULL;
}
-/* when returning 2 - the frame isnt found but before/after frames are */
+/**
+ * When returning 2 - the frame isn't found but before/after frames are.
+ */
int BKE_mask_layer_shape_find_frame_range(MaskLayer *masklay,
const float frame,
MaskLayerShape **r_masklay_shape_a,
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index b01c1189fd1..c12541b3b22 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -71,6 +71,7 @@
/* used in UI and render */
Material defmaterial;
+Material defgpencil_material;
static CLG_LogRef LOG = {"bke.material"};
@@ -78,6 +79,13 @@ static CLG_LogRef LOG = {"bke.material"};
void init_def_material(void)
{
BKE_material_init(&defmaterial);
+ BKE_material_gpencil_init(&defgpencil_material);
+}
+
+/* Free the GPencil data of the default material, creator.c */
+void BKE_material_gpencil_default_free(void)
+{
+ MEM_SAFE_FREE(defgpencil_material.gp_style);
}
/** Free (or release) any data used by this material (does not free the material itself). */
@@ -144,6 +152,16 @@ void BKE_material_init(Material *ma)
ma->blend_shadow = MA_BS_SOLID;
}
+void BKE_material_gpencil_init(Material *ma)
+{
+ BKE_material_init(ma);
+
+ /* grease pencil settings */
+ strcpy(ma->id.name, "MADefault GPencil");
+ BKE_material_init_gpencil_settings(ma);
+ add_v3_fl(&ma->gp_style->stroke_rgba[0], 0.6f);
+}
+
Material *BKE_material_add(Main *bmain, const char *name)
{
Material *ma;
@@ -180,10 +198,13 @@ Material *BKE_material_add_gpencil(Main *bmain, const char *name)
*/
void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_src, const int flag)
{
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+ /* We always need allocation of our private ID data. */
+ const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE;
+
if (ma_src->nodetree) {
- /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level
- * (see BKE_libblock_copy_ex()). */
- BKE_id_copy_ex(bmain, (ID *)ma_src->nodetree, (ID **)&ma_dst->nodetree, flag);
+ BKE_id_copy_ex(bmain, (ID *)ma_src->nodetree, (ID **)&ma_dst->nodetree, flag_private_id_data);
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
@@ -461,7 +482,7 @@ void BKE_material_append_id(Main *bmain, ID *id, Material *ma)
}
}
-Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data)
+Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i)
{
short index = (short)index_i;
Material *ret = NULL;
@@ -489,10 +510,7 @@ Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data
test_all_objects_materials(bmain, id);
}
- if (update_data) {
- /* decrease mat_nr index */
- material_data_index_remove_id(id, index);
- }
+ material_data_index_remove_id(id, index);
DEG_id_tag_update(id, ID_RECALC_COPY_ON_WRITE);
DEG_relations_tag_update(bmain);
@@ -502,7 +520,7 @@ Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data
return ret;
}
-void BKE_material_clear_id(Main *bmain, ID *id, bool update_data)
+void BKE_material_clear_id(Main *bmain, ID *id)
{
Material ***matar;
if ((matar = give_matarar_id(id))) {
@@ -516,12 +534,9 @@ void BKE_material_clear_id(Main *bmain, ID *id, bool update_data)
MEM_freeN(*matar);
*matar = NULL;
}
- test_all_objects_materials(bmain, id);
- if (update_data) {
- /* decrease mat_nr index */
- material_data_index_clear_id(id);
- }
+ test_all_objects_materials(bmain, id);
+ material_data_index_clear_id(id);
DEG_id_tag_update(id, ID_RECALC_COPY_ON_WRITE);
DEG_relations_tag_update(bmain);
@@ -586,6 +601,17 @@ Material *give_current_material(Object *ob, short act)
return ma_p ? *ma_p : NULL;
}
+Material *BKE_material_gpencil_get(Object *ob, short act)
+{
+ Material *ma = give_current_material(ob, act);
+ if (ma != NULL) {
+ return ma;
+ }
+ else {
+ return &defgpencil_material;
+ }
+}
+
MaterialGPencilStyle *BKE_material_gpencil_settings_get(Object *ob, short act)
{
Material *ma = give_current_material(ob, act);
@@ -597,7 +623,7 @@ MaterialGPencilStyle *BKE_material_gpencil_settings_get(Object *ob, short act)
return ma->gp_style;
}
else {
- return NULL;
+ return defgpencil_material.gp_style;
}
}
@@ -1076,10 +1102,6 @@ bool BKE_object_material_slot_remove(Main *bmain, Object *ob)
}
/* check indices from gpencil */
else if (ob->type == OB_GPENCIL) {
- /* need one color */
- if (ob->totcol == 0) {
- BKE_gpencil_object_material_ensure_from_active_input_material(bmain, ob);
- }
BKE_gpencil_material_index_reassign((bGPdata *)ob->data, ob->totcol, actcol - 1);
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index d6fa071009e..19009322975 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -364,12 +364,13 @@ bool BKE_mball_is_any_unselected(const MetaBall *mb)
return false;
}
-/* \brief copy some properties from object to other metaball object with same base name
+/**
+ * \brief copy some properties from object to other metaball object with same base name
*
* When some properties (wiresize, threshold, update flags) of metaball are changed, then this
* properties are copied to all metaballs in same "group" (metaballs with same base name: MBall,
* MBall.001, MBall.002, etc). The most important is to copy properties to the base metaball,
- * because this metaball influence polygonisation of metaballs. */
+ * because this metaball influence polygonization of metaballs. */
void BKE_mball_properties_copy(Scene *scene, Object *active_object)
{
Scene *sce_iter = scene;
@@ -525,7 +526,7 @@ bool BKE_mball_center_bounds(const MetaBall *mb, float r_cent[3])
return false;
}
-void BKE_mball_transform(MetaBall *mb, float mat[4][4], const bool do_props)
+void BKE_mball_transform(MetaBall *mb, const float mat[4][4], const bool do_props)
{
float quat[4];
const float scale = mat4_to_scale(mat);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 4f39d34574e..61b841591a4 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -661,13 +661,13 @@ Mesh *BKE_mesh_new_nomain(
return mesh;
}
-static Mesh *mesh_new_nomain_from_template_ex(const Mesh *me_src,
- int verts_len,
- int edges_len,
- int tessface_len,
- int loops_len,
- int polys_len,
- CustomData_MeshMasks mask)
+Mesh *BKE_mesh_new_nomain_from_template_ex(const Mesh *me_src,
+ int verts_len,
+ int edges_len,
+ int tessface_len,
+ int loops_len,
+ int polys_len,
+ CustomData_MeshMasks mask)
{
/* Only do tessface if we are creating tessfaces or copying from mesh with only tessfaces. */
const bool do_tessface = (tessface_len || ((me_src->totface != 0) && (me_src->totpoly == 0)));
@@ -713,7 +713,7 @@ Mesh *BKE_mesh_new_nomain_from_template(const Mesh *me_src,
int loops_len,
int polys_len)
{
- return mesh_new_nomain_from_template_ex(
+ return BKE_mesh_new_nomain_from_template_ex(
me_src, verts_len, edges_len, tessface_len, loops_len, polys_len, CD_MASK_EVERYTHING);
}
@@ -801,7 +801,7 @@ Mesh *BKE_mesh_from_editmesh_with_coords_thin_wrap(BMEditMesh *em,
me->runtime.is_original = true;
if (vertexCos) {
/* We will own this array in the future. */
- BKE_mesh_apply_vert_coords(me, vertexCos);
+ BKE_mesh_vert_coords_apply(me, vertexCos);
MEM_freeN(vertexCos);
me->runtime.is_original = false;
}
@@ -813,92 +813,6 @@ void BKE_mesh_make_local(Main *bmain, Mesh *me, const bool lib_local)
BKE_id_make_local_generic(bmain, &me->id, true, lib_local);
}
-bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me,
- const int loop_index,
- const int face_index,
- const char *new_name,
- const bool do_tessface)
-{
- CustomData *ldata, *fdata;
- CustomDataLayer *cdlu, *cdlf;
-
- if (me->edit_mesh) {
- ldata = &me->edit_mesh->bm->ldata;
- fdata = NULL; /* No tessellated data in BMesh! */
- }
- else {
- ldata = &me->ldata;
- fdata = &me->fdata;
- }
-
- cdlu = &ldata->layers[loop_index];
- cdlf = (face_index != -1) && fdata && do_tessface ? &fdata->layers[face_index] : NULL;
-
- if (cdlu->name != new_name) {
- /* Mesh validate passes a name from the CD layer as the new name,
- * Avoid memcpy from self to self in this case.
- */
- BLI_strncpy(cdlu->name, new_name, sizeof(cdlu->name));
- CustomData_set_layer_unique_name(ldata, loop_index);
- }
-
- if (cdlf == NULL) {
- return false;
- }
-
- BLI_strncpy(cdlf->name, cdlu->name, sizeof(cdlf->name));
- CustomData_set_layer_unique_name(fdata, face_index);
-
- return true;
-}
-
-bool BKE_mesh_uv_cdlayer_rename(Mesh *me,
- const char *old_name,
- const char *new_name,
- bool do_tessface)
-{
- CustomData *ldata, *fdata;
- if (me->edit_mesh) {
- ldata = &me->edit_mesh->bm->ldata;
- /* No tessellated data in BMesh! */
- fdata = NULL;
- do_tessface = false;
- }
- else {
- ldata = &me->ldata;
- fdata = &me->fdata;
- do_tessface = (do_tessface && fdata->totlayer);
- }
-
- {
- const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV);
- const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1;
- int lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name);
- int fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1;
-
- /* None of those cases should happen, in theory!
- * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers!
- */
- if (lidx == -1) {
- if (fidx == -1) {
- /* No layer found with this name! */
- return false;
- }
- else {
- lidx = fidx;
- }
- }
-
- /* Go back to absolute indices! */
- lidx += lidx_start;
- if (fidx != -1) {
- fidx += fidx_start;
- }
-
- return BKE_mesh_uv_cdlayer_rename_index(me, lidx, fidx, new_name, do_tessface);
- }
-}
-
void BKE_mesh_boundbox_calc(Mesh *me, float r_loc[3], float r_size[3])
{
BoundBox *bb;
@@ -1273,54 +1187,21 @@ void BKE_mesh_material_remap(Mesh *me, const unsigned int *remap, unsigned int r
#undef MAT_NR_REMAP
}
-void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth)
+void BKE_mesh_smooth_flag_set(Mesh *me, const bool use_smooth)
{
- Mesh *me = meshOb->data;
- int i;
-
- for (i = 0; i < me->totpoly; i++) {
- MPoly *mp = &me->mpoly[i];
-
- if (enableSmooth) {
- mp->flag |= ME_SMOOTH;
- }
- else {
- mp->flag &= ~ME_SMOOTH;
+ if (use_smooth) {
+ for (int i = 0; i < me->totpoly; i++) {
+ me->mpoly[i].flag |= ME_SMOOTH;
}
}
-
- for (i = 0; i < me->totface; i++) {
- MFace *mf = &me->mface[i];
-
- if (enableSmooth) {
- mf->flag |= ME_SMOOTH;
- }
- else {
- mf->flag &= ~ME_SMOOTH;
+ else {
+ for (int i = 0; i < me->totpoly; i++) {
+ me->mpoly[i].flag &= ~ME_SMOOTH;
}
}
}
/**
- * Return a newly MEM_malloc'd array of all the mesh vertex locations
- * \note \a r_verts_len may be NULL
- */
-float (*BKE_mesh_vertexCos_get(const Mesh *me, int *r_verts_len))[3]
-{
- int i, verts_len = me->totvert;
- float(*cos)[3] = MEM_malloc_arrayN(verts_len, sizeof(*cos), "vertexcos1");
-
- if (r_verts_len) {
- *r_verts_len = verts_len;
- }
- for (i = 0; i < verts_len; i++) {
- copy_v3_v3(cos[i], me->mvert[i].co);
- }
-
- return cos;
-}
-
-/**
* Find the index of the loop in 'poly' which references vertex,
* returns -1 if not found
*/
@@ -1471,7 +1352,7 @@ void BKE_mesh_ensure_navmesh(Mesh *me)
void BKE_mesh_tessface_calc(Mesh *mesh)
{
- mesh->totface = BKE_mesh_recalc_tessellation(
+ mesh->totface = BKE_mesh_tessface_calc_ex(
&mesh->fdata,
&mesh->ldata,
&mesh->pdata,
@@ -1665,35 +1546,56 @@ void BKE_mesh_count_selected_items(const Mesh *mesh, int r_count[3])
/* We could support faces in paint modes. */
}
-void BKE_mesh_apply_vert_coords(Mesh *mesh, float (*vertCoords)[3])
+void BKE_mesh_vert_coords_get(const Mesh *mesh, float (*vert_coords)[3])
{
- MVert *vert;
- int i;
-
- /* this will just return the pointer if it wasn't a referenced layer */
- vert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
- mesh->mvert = vert;
+ const MVert *mv = mesh->mvert;
+ for (int i = 0; i < mesh->totvert; i++, mv++) {
+ copy_v3_v3(vert_coords[i], mv->co);
+ }
+}
- for (i = 0; i < mesh->totvert; ++i, ++vert) {
- copy_v3_v3(vert->co, vertCoords[i]);
+float (*BKE_mesh_vert_coords_alloc(const Mesh *mesh, int *r_vert_len))[3]
+{
+ float(*vert_coords)[3] = MEM_mallocN(sizeof(float[3]) * mesh->totvert, __func__);
+ BKE_mesh_vert_coords_get(mesh, vert_coords);
+ if (r_vert_len) {
+ *r_vert_len = mesh->totvert;
}
+ return vert_coords;
+}
+void BKE_mesh_vert_coords_apply(Mesh *mesh, const float (*vert_coords)[3])
+{
+ /* This will just return the pointer if it wasn't a referenced layer. */
+ MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
+ mesh->mvert = mv;
+ for (int i = 0; i < mesh->totvert; i++, mv++) {
+ copy_v3_v3(mv->co, vert_coords[i]);
+ }
mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
}
-void BKE_mesh_apply_vert_normals(Mesh *mesh, short (*vertNormals)[3])
+void BKE_mesh_vert_coords_apply_with_mat4(Mesh *mesh,
+ const float (*vert_coords)[3],
+ const float mat[4][4])
{
- MVert *vert;
- int i;
-
- /* this will just return the pointer if it wasn't a referenced layer */
- vert = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
- mesh->mvert = vert;
-
- for (i = 0; i < mesh->totvert; ++i, ++vert) {
- copy_v3_v3_short(vert->no, vertNormals[i]);
+ /* This will just return the pointer if it wasn't a referenced layer. */
+ MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
+ mesh->mvert = mv;
+ for (int i = 0; i < mesh->totvert; i++, mv++) {
+ mul_v3_m4v3(mv->co, mat, vert_coords[i]);
}
+ mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
+}
+void BKE_mesh_vert_normals_apply(Mesh *mesh, const short (*vert_normals)[3])
+{
+ /* This will just return the pointer if it wasn't a referenced layer. */
+ MVert *mv = CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert);
+ mesh->mvert = mv;
+ for (int i = 0; i < mesh->totvert; i++, mv++) {
+ copy_v3_v3_short(mv->no, vert_normals[i]);
+ }
mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
}
diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c
index 3a2ba078dce..e072a37acee 100644
--- a/source/blender/blenkernel/intern/mesh_convert.c
+++ b/source/blender/blenkernel/intern/mesh_convert.c
@@ -1341,11 +1341,11 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph,
if (mti->type == eModifierTypeType_OnlyDeform) {
int numVerts;
- float(*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts);
+ float(*deformedVerts)[3] = BKE_mesh_vert_coords_alloc(me, &numVerts);
BKE_id_copy_ex(NULL, &me->id, (ID **)&result, LIB_ID_COPY_LOCALIZE);
mti->deformVerts(md_eval, &mectx, result, deformedVerts, numVerts);
- BKE_mesh_apply_vert_coords(result, deformedVerts);
+ BKE_mesh_vert_coords_apply(result, deformedVerts);
if (build_shapekey_layers) {
add_shapekey_layers(result, me);
@@ -1434,7 +1434,6 @@ static void shapekey_layers_to_keyblocks(Mesh *mesh_src, Mesh *mesh_dst, int act
}
}
-/* This is a Mesh-based copy of DM_to_mesh() */
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
Mesh *mesh_dst,
Object *ob,
@@ -1442,7 +1441,7 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
bool take_ownership)
{
/* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */
- /* TODO(Sybren): the above claim came from DM_to_mesh();
+ /* TODO(Sybren): the above claim came from 2.7x derived-mesh code (DM_to_mesh);
* check whether it is still true with Mesh */
Mesh tmp = *mesh_dst;
int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly;
@@ -1594,7 +1593,6 @@ void BKE_mesh_nomain_to_mesh(Mesh *mesh_src,
}
}
-/* This is a Mesh-based copy of DM_to_meshkey() */
void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb)
{
int a, totvert = mesh_src->totvert;
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 2ea275cdfb0..38762109167 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -448,64 +448,6 @@ void BKE_mesh_calc_normals(Mesh *mesh)
mesh->runtime.cd_dirty_vert &= ~CD_MASK_NORMAL;
}
-void BKE_mesh_calc_normals_tessface(
- MVert *mverts, int numVerts, const MFace *mfaces, int numFaces, float (*r_faceNors)[3])
-{
- float(*tnorms)[3] = MEM_calloc_arrayN((size_t)numVerts, sizeof(*tnorms), "tnorms");
- float(*fnors)[3] = (r_faceNors) ?
- r_faceNors :
- MEM_calloc_arrayN((size_t)numFaces, sizeof(*fnors), "meshnormals");
- int i;
-
- if (!tnorms || !fnors) {
- goto cleanup;
- }
-
- for (i = 0; i < numFaces; i++) {
- const MFace *mf = &mfaces[i];
- float *f_no = fnors[i];
- float *n4 = (mf->v4) ? tnorms[mf->v4] : NULL;
- const float *c4 = (mf->v4) ? mverts[mf->v4].co : NULL;
-
- if (mf->v4) {
- normal_quad_v3(
- f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co, mverts[mf->v4].co);
- }
- else {
- normal_tri_v3(f_no, mverts[mf->v1].co, mverts[mf->v2].co, mverts[mf->v3].co);
- }
-
- accumulate_vertex_normals_v3(tnorms[mf->v1],
- tnorms[mf->v2],
- tnorms[mf->v3],
- n4,
- f_no,
- mverts[mf->v1].co,
- mverts[mf->v2].co,
- mverts[mf->v3].co,
- c4);
- }
-
- /* following Mesh convention; we use vertex coordinate itself for normal in this case */
- for (i = 0; i < numVerts; i++) {
- MVert *mv = &mverts[i];
- float *no = tnorms[i];
-
- if (UNLIKELY(normalize_v3(no) == 0.0f)) {
- normalize_v3_v3(no, mv->co);
- }
-
- normal_float_to_short_v3(mv->no, no);
- }
-
-cleanup:
- MEM_freeN(tnorms);
-
- if (fnors != r_faceNors) {
- MEM_freeN(fnors);
- }
-}
-
void BKE_mesh_calc_normals_looptri(MVert *mverts,
int numVerts,
const MLoop *mloop,
@@ -1320,7 +1262,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
}
// print_v2("new clnors", clnors_avg);
}
- /* Extra bonus: since smallstack is local to this func,
+ /* Extra bonus: since small-stack is local to this function,
* no more need to empty it at all cost! */
BKE_lnor_space_custom_data_to_normal(lnor_space, *clnor_ref, lnor);
@@ -1336,7 +1278,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
copy_v3_v3(nor, lnor);
}
}
- /* Extra bonus: since smallstack is local to this func,
+ /* Extra bonus: since small-stack is local to this funcion,
* no more need to empty it at all cost! */
}
}
@@ -3003,14 +2945,14 @@ void BKE_mesh_tangent_loops_to_tessdata(CustomData *fdata,
*
* \return number of tessellation faces.
*/
-int BKE_mesh_recalc_tessellation(CustomData *fdata,
- CustomData *ldata,
- CustomData *pdata,
- MVert *mvert,
- int totface,
- int totloop,
- int totpoly,
- const bool do_face_nor_copy)
+int BKE_mesh_tessface_calc_ex(CustomData *fdata,
+ CustomData *ldata,
+ CustomData *pdata,
+ MVert *mvert,
+ int totface,
+ int totloop,
+ int totpoly,
+ const bool do_face_nor_copy)
{
/* use this to avoid locking pthread for _every_ polygon
* and calling the fill function */
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index 78c0fa184f4..d908a248a28 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -845,7 +845,7 @@ static bool poly_is_island_boundary_smooth_cb(const MPoly *mp,
const MPoly *mp_other = (mp == &mpoly_array[edge_poly_map->indices[0]]) ?
&mpoly_array[edge_poly_map->indices[1]] :
&mpoly_array[edge_poly_map->indices[0]];
- return (mp_other->flag & ME_SMOOTH) != 0;
+ return (mp_other->flag & ME_SMOOTH) == 0;
}
return true;
}
diff --git a/source/blender/blenkernel/intern/mesh_merge.c b/source/blender/blenkernel/intern/mesh_merge.c
index 71cc20c78b7..ae808b85323 100644
--- a/source/blender/blenkernel/intern/mesh_merge.c
+++ b/source/blender/blenkernel/intern/mesh_merge.c
@@ -235,7 +235,7 @@ static bool poly_gset_compare_fn(const void *k1, const void *k2)
* but the additional checks are costly and not necessary in the case of mirror,
* because each vertex is only merged to its own mirror.
*
- * \note #BKE_mesh_recalc_tessellation has to run on the returned DM
+ * \note #BKE_mesh_tessface_calc_ex has to run on the returned DM
* if you want to access tessfaces.
*/
Mesh *BKE_mesh_merge_verts(Mesh *mesh,
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index db158ca8fb2..834008ca1ac 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -291,7 +291,7 @@ void BKE_mesh_remap_find_best_match_from_mesh(const MVert *verts_dst,
float best_match = FLT_MAX, match;
const int numverts_src = me_src->totvert;
- float(*vcos_src)[3] = BKE_mesh_vertexCos_get(me_src, NULL);
+ float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL);
mesh_calc_eigen_matrix(NULL, (const float(*)[3])vcos_src, numverts_src, mat_src);
mesh_calc_eigen_matrix(verts_dst, NULL, numverts_dst, mat_dst);
@@ -548,7 +548,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
}
else if (ELEM(mode, MREMAP_MODE_VERT_EDGE_NEAREST, MREMAP_MODE_VERT_EDGEINTERP_NEAREST)) {
MEdge *edges_src = me_src->medge;
- float(*vcos_src)[3] = BKE_mesh_vertexCos_get(me_src, NULL);
+ float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL);
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_EDGES, 2);
nearest.index = -1;
@@ -602,7 +602,7 @@ void BKE_mesh_remap_calc_verts_from_mesh(const int mode,
MREMAP_MODE_VERT_POLYINTERP_VNORPROJ)) {
MPoly *polys_src = me_src->mpoly;
MLoop *loops_src = me_src->mloop;
- float(*vcos_src)[3] = BKE_mesh_vertexCos_get(me_src, NULL);
+ float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL);
size_t tmp_buff_size = MREMAP_DEFAULT_BUFSIZE;
float(*vcos)[3] = MEM_mallocN(sizeof(*vcos) * tmp_buff_size, __func__);
@@ -752,7 +752,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
const int num_verts_src = me_src->totvert;
const int num_edges_src = me_src->totedge;
MEdge *edges_src = me_src->medge;
- float(*vcos_src)[3] = BKE_mesh_vertexCos_get(me_src, NULL);
+ float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL);
MeshElemMap *vert_to_edge_src_map;
int *vert_to_edge_src_map_mem;
@@ -901,7 +901,7 @@ void BKE_mesh_remap_calc_edges_from_mesh(const int mode,
MEdge *edges_src = me_src->medge;
MPoly *polys_src = me_src->mpoly;
MLoop *loops_src = me_src->mloop;
- float(*vcos_src)[3] = BKE_mesh_vertexCos_get(me_src, NULL);
+ float(*vcos_src)[3] = BKE_mesh_vert_coords_alloc(me_src, NULL);
BKE_bvhtree_from_mesh_get(&treedata, me_src, BVHTREE_FROM_LOOPTRI, 2);
@@ -1350,7 +1350,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
size_t islands_res_buff_size = MREMAP_DEFAULT_BUFSIZE;
if (!use_from_vert) {
- vcos_src = BKE_mesh_vertexCos_get(me_src, NULL);
+ vcos_src = BKE_mesh_vert_coords_alloc(me_src, NULL);
vcos_interp = MEM_mallocN(sizeof(*vcos_interp) * buff_size_interp, __func__);
indices_interp = MEM_mallocN(sizeof(*indices_interp) * buff_size_interp, __func__);
@@ -1553,7 +1553,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
num_verts_active,
0.0,
2,
- 6);
+ 6,
+ 0,
+ NULL);
}
MEM_freeN(verts_active);
@@ -1594,7 +1596,9 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
num_looptri_active,
0.0,
2,
- 6);
+ 6,
+ 0,
+ NULL);
}
MEM_freeN(looptri_active);
diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c
index d939267ac5a..9947b96105d 100644
--- a/source/blender/blenkernel/intern/multires_reshape.c
+++ b/source/blender/blenkernel/intern/multires_reshape.c
@@ -891,7 +891,7 @@ bool multiresModifier_reshapeFromObject(struct Depsgraph *depsgraph,
Object *src_eval = DEG_get_evaluated_object(depsgraph, src);
Mesh *src_mesh_eval = mesh_get_eval_final(depsgraph, scene_eval, src_eval, &CD_MASK_BAREMESH);
int num_deformed_verts;
- float(*deformed_verts)[3] = BKE_mesh_vertexCos_get(src_mesh_eval, &num_deformed_verts);
+ float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(src_mesh_eval, &num_deformed_verts);
bool result = multires_reshape_from_vertcos(
depsgraph, dst, &reshape_mmd, deformed_verts, num_deformed_verts, false);
MEM_freeN(deformed_verts);
@@ -926,7 +926,7 @@ bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph,
* deformation modifiers will be applied though). */
Mesh *multires_mesh = BKE_multires_create_mesh(depsgraph, scene_eval, &highest_mmd, object);
int num_deformed_verts;
- float(*deformed_verts)[3] = BKE_mesh_vertexCos_get(multires_mesh, &num_deformed_verts);
+ float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(multires_mesh, &num_deformed_verts);
/* Apply deformation modifier on the multires, */
const ModifierEvalContext modifier_ctx = {
.depsgraph = depsgraph,
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 986571e34bd..2eba71fa6bd 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -1406,6 +1406,7 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
}
else {
ntree = MEM_callocN(sizeof(bNodeTree), "new node tree");
+ ntree->id.flag |= LIB_PRIVATE_DATA;
*((short *)ntree->id.name) = ID_NT;
BLI_strncpy(ntree->id.name + 2, name, sizeof(ntree->id.name));
}
@@ -2172,6 +2173,7 @@ void ntreeSetOutput(bNodeTree *ntree)
* might be different for editor or for "real" use... */
}
+/* Returns the private NodeTree object of the datablock, if it has one. */
bNodeTree *ntreeFromID(const ID *id)
{
switch (GS(id->name)) {
@@ -2192,6 +2194,28 @@ bNodeTree *ntreeFromID(const ID *id)
}
}
+/* Finds and returns the datablock that privately owns the given tree, or NULL. */
+ID *BKE_node_tree_find_owner_ID(Main *bmain, struct bNodeTree *ntree)
+{
+ ListBase *lists[] = {&bmain->materials,
+ &bmain->lights,
+ &bmain->worlds,
+ &bmain->textures,
+ &bmain->scenes,
+ &bmain->linestyles,
+ NULL};
+
+ for (int i = 0; lists[i] != NULL; i++) {
+ LISTBASE_FOREACH (ID *, id, lists[i]) {
+ if (ntreeFromID(id) == ntree) {
+ return id;
+ }
+ }
+ }
+
+ return NULL;
+}
+
void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist, const bool lib_local)
{
BKE_id_make_local_generic(bmain, &ntree->id, id_in_mainlist, lib_local);
@@ -2799,6 +2823,16 @@ int nodeSocketIsHidden(bNodeSocket *sock)
return ((sock->flag & (SOCK_HIDDEN | SOCK_UNAVAIL)) != 0);
}
+void nodeSetSocketAvailability(bNodeSocket *sock, bool is_available)
+{
+ if (is_available) {
+ sock->flag &= ~SOCK_UNAVAIL;
+ }
+ else {
+ sock->flag |= SOCK_UNAVAIL;
+ }
+}
+
/* ************** Node Clipboard *********** */
#define USE_NODE_CB_VALIDATE
@@ -3222,11 +3256,6 @@ void ntreeTagUsedSockets(bNodeTree *ntree)
}
for (link = ntree->links.first; link; link = link->next) {
- /* link is unused if either side is disabled */
- if ((link->fromsock->flag & SOCK_UNAVAIL) || (link->tosock->flag & SOCK_UNAVAIL)) {
- continue;
- }
-
link->fromsock->flag |= SOCK_IN_USE;
link->tosock->flag |= SOCK_IN_USE;
}
@@ -3928,6 +3957,7 @@ static void registerShaderNodes(void)
register_node_type_sh_tex_brick();
register_node_type_sh_tex_pointdensity();
register_node_type_sh_tex_ies();
+ register_node_type_sh_tex_white_noise();
}
static void registerTextureNodes(void)
@@ -3954,6 +3984,7 @@ static void registerTextureNodes(void)
register_node_type_sh_tangent();
register_node_type_sh_normal_map();
register_node_type_sh_hair_info();
+ register_node_type_sh_volume_info();
register_node_type_tex_checker();
register_node_type_tex_texture();
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index d95c02cdf7f..ed517bfc513 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2985,6 +2985,15 @@ bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const Re
}
}
+ if (visibility_flag & OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED) {
+ float proj[3];
+ project_plane_v3_v3v3(proj, ob->obmat[2], rv3d->viewinv[2]);
+ const float proj_length_sq = len_squared_v3(proj);
+ if (proj_length_sq > 1e-5f) {
+ return false;
+ }
+ }
+
return true;
}
@@ -3587,7 +3596,7 @@ bool BKE_object_shapekey_free(Main *bmain, Object *ob)
BKE_id_free_us(bmain, key);
- return false;
+ return true;
}
bool BKE_object_shapekey_remove(Main *bmain, Object *ob, KeyBlock *kb)
@@ -3871,7 +3880,7 @@ int BKE_object_scenes_users_get(Main *bmain, Object *ob)
{
int num_scenes = 0;
for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
- if (BKE_collection_has_object_recursive(BKE_collection_master(scene), ob)) {
+ if (BKE_collection_has_object_recursive(scene->master_collection, ob)) {
num_scenes++;
}
}
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 9b717650e8e..3a330ea0d5a 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -436,7 +436,7 @@ void BKE_object_eval_eval_base_flags(Depsgraph *depsgraph,
BKE_base_eval_flags(base);
/* For render, compute base visibility again since BKE_base_eval_flags
- * assumed viewport visibility. Selectability does not matter here. */
+ * assumed viewport visibility. Select-ability does not matter here. */
if (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER) {
if (base->flag & BASE_ENABLED_RENDER) {
base->flag |= BASE_VISIBLE;
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 39fb668c873..fcceebc3913 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -519,7 +519,7 @@ static void ocean_compute_htilda(void *__restrict userdata,
int j;
- /* note the <= _N/2 here, see the fftw doco
+ /* Note the <= _N/2 here, see the FFTW documentation
* about the mechanics of the complex->real fft storage. */
for (j = 0; j <= o->_N / 2; ++j) {
fftw_complex exp_param1;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 4a41ffbfa8c..a46bb36c883 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -1222,10 +1222,10 @@ static void sculpt_update_object(
BKE_sculptsession_free_deformMats(ss);
ss->orig_cos = (ss->kb) ? BKE_keyblock_convert_to_vertcos(ob, ss->kb) :
- BKE_mesh_vertexCos_get(me, NULL);
+ BKE_mesh_vert_coords_alloc(me, NULL);
BKE_crazyspace_build_sculpt(depsgraph, scene, ob, &ss->deform_imats, &ss->deform_cos);
- BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos, me->totvert);
+ BKE_pbvh_vert_coords_apply(ss->pbvh, ss->deform_cos, me->totvert);
for (a = 0; a < me->totvert; ++a) {
invert_m3(ss->deform_imats[a]);
@@ -1242,14 +1242,14 @@ static void sculpt_update_object(
/* if pbvh is deformed, key block is already applied to it */
if (ss->kb) {
- bool pbvh_deformed = BKE_pbvh_isDeformed(ss->pbvh);
+ bool pbvh_deformed = BKE_pbvh_is_deformed(ss->pbvh);
if (!pbvh_deformed || ss->deform_cos == NULL) {
float(*vertCos)[3] = BKE_keyblock_convert_to_vertcos(ob, ss->kb);
if (vertCos) {
if (!pbvh_deformed) {
/* apply shape keys coordinates to PBVH */
- BKE_pbvh_apply_vertCos(ss->pbvh, vertCos, me->totvert);
+ BKE_pbvh_vert_coords_apply(ss->pbvh, vertCos, me->totvert);
}
if (ss->deform_cos == NULL) {
ss->deform_cos = vertCos;
@@ -1477,8 +1477,8 @@ static PBVH *build_pbvh_from_regular_mesh(Object *ob, Mesh *me_eval_deform)
const bool is_deformed = check_sculpt_object_deformed(ob, true);
if (is_deformed && me_eval_deform != NULL) {
int totvert;
- float(*v_cos)[3] = BKE_mesh_vertexCos_get(me_eval_deform, &totvert);
- BKE_pbvh_apply_vertCos(pbvh, v_cos, totvert);
+ float(*v_cos)[3] = BKE_mesh_vert_coords_alloc(me_eval_deform, &totvert);
+ BKE_pbvh_vert_coords_apply(pbvh, v_cos, totvert);
MEM_freeN(v_cos);
}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index ffeba0148a2..2de8d4a643a 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -2691,7 +2691,7 @@ static void psys_thread_create_path(ParticleTask *task,
pa = &psys->particles[cpa->parent];
par = pcache[cpa->parent];
- /* If particle is unexisting, try to pick a viable parent from particles
+ /* If particle is non-existing, try to pick a viable parent from particles
* used for interpolation. */
for (k = 0; k < 4 && pa && (pa->flag & PARS_UNEXIST); k++) {
if (cpa->pa[k] >= 0) {
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 31484b59127..e328ae8952e 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -3490,10 +3490,10 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
psys->clmd->sim_parms->effector_weights = psys->part->effector_weights;
BKE_id_copy_ex(NULL, &psys->hair_in_mesh->id, (ID **)&psys->hair_out_mesh, LIB_ID_COPY_LOCALIZE);
- deformedVerts = BKE_mesh_vertexCos_get(psys->hair_out_mesh, NULL);
+ deformedVerts = BKE_mesh_vert_coords_alloc(psys->hair_out_mesh, NULL);
clothModifier_do(
psys->clmd, sim->depsgraph, sim->scene, sim->ob, psys->hair_in_mesh, deformedVerts);
- BKE_mesh_apply_vert_coords(psys->hair_out_mesh, deformedVerts);
+ BKE_mesh_vert_coords_apply(psys->hair_out_mesh, deformedVerts);
MEM_freeN(deformedVerts);
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 64a16a0e3be..7a8c082842e 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -533,7 +533,7 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
* Do a full rebuild with on Mesh data structure.
*
* \note Unlike mpoly/mloop/verts, looptri is **totally owned** by PBVH
- * (which means it may rewrite it if needed, see #BKE_pbvh_apply_vertCos().
+ * (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply().
*/
void BKE_pbvh_build_mesh(PBVH *bvh,
const MPoly *mpoly,
@@ -1753,14 +1753,21 @@ static bool pbvh_faces_node_raycast(PBVH *bvh,
const PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
+ const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
- float *depth)
+ float *depth,
+ int *r_active_vertex_index,
+ float *r_face_normal)
{
const MVert *vert = bvh->verts;
const MLoop *mloop = bvh->mloop;
const int *faces = node->prim_indices;
int i, totface = node->totprim;
bool hit = false;
+ float min_depth = FLT_MAX;
+ float location[3] = {0.0f};
+ float nearest_vertex_co[3];
+ copy_v3_fl(nearest_vertex_co, 0.0f);
for (i = 0; i < totface; ++i) {
const MLoopTri *lt = &bvh->looptri[faces[i]];
@@ -1787,6 +1794,22 @@ static bool pbvh_faces_node_raycast(PBVH *bvh,
vert[mloop[lt->tri[1]].v].co,
vert[mloop[lt->tri[2]].v].co,
depth);
+
+ if (hit && *depth < min_depth) {
+ min_depth = *depth;
+ normal_tri_v3(r_face_normal,
+ vert[mloop[lt->tri[0]].v].co,
+ vert[mloop[lt->tri[1]].v].co,
+ vert[mloop[lt->tri[2]].v].co);
+ madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
+ for (int j = 0; j < 3; j++) {
+ if (len_squared_v3v3(location, vert[mloop[lt->tri[j]].v].co) <
+ len_squared_v3v3(location, nearest_vertex_co)) {
+ copy_v3_v3(nearest_vertex_co, vert[mloop[lt->tri[j]].v].co);
+ *r_active_vertex_index = mloop[lt->tri[j]].v;
+ }
+ }
+ }
}
}
@@ -1857,8 +1880,11 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
float (*origco)[3],
bool use_origco,
const float ray_start[3],
+ const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
- float *depth)
+ float *depth,
+ int *active_vertex_index,
+ float *face_normal)
{
bool hit = false;
@@ -1868,13 +1894,29 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
switch (bvh->type) {
case PBVH_FACES:
- hit |= pbvh_faces_node_raycast(bvh, node, origco, ray_start, isect_precalc, depth);
+ hit |= pbvh_faces_node_raycast(bvh,
+ node,
+ origco,
+ ray_start,
+ ray_normal,
+ isect_precalc,
+ depth,
+ active_vertex_index,
+ face_normal);
break;
case PBVH_GRIDS:
hit |= pbvh_grids_node_raycast(bvh, node, origco, ray_start, isect_precalc, depth);
break;
case PBVH_BMESH:
- hit = pbvh_bmesh_node_raycast(node, ray_start, isect_precalc, depth, use_origco);
+ BM_mesh_elem_index_ensure(bvh->bm, BM_VERT);
+ hit = pbvh_bmesh_node_raycast(node,
+ ray_start,
+ ray_normal,
+ isect_precalc,
+ depth,
+ use_origco,
+ active_vertex_index,
+ face_normal);
break;
}
@@ -2306,7 +2348,7 @@ void BKE_pbvh_node_layer_disp_free(PBVHNode *node)
}
}
-float (*BKE_pbvh_get_vertCos(PBVH *pbvh))[3]
+float (*BKE_pbvh_vert_coords_alloc(PBVH *pbvh))[3]
{
float(*vertCos)[3] = NULL;
@@ -2324,7 +2366,7 @@ float (*BKE_pbvh_get_vertCos(PBVH *pbvh))[3]
return vertCos;
}
-void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3], const int totvert)
+void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const float (*vertCos)[3], const int totvert)
{
if (totvert != pbvh->totvert) {
BLI_assert(!"PBVH: Given deforming vcos number does not natch PBVH vertex number!");
@@ -2368,7 +2410,7 @@ void BKE_pbvh_apply_vertCos(PBVH *pbvh, float (*vertCos)[3], const int totvert)
}
}
-bool BKE_pbvh_isDeformed(PBVH *pbvh)
+bool BKE_pbvh_is_deformed(PBVH *pbvh)
{
return pbvh->deformed;
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 1d8088c6605..c04e172f116 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -1508,12 +1508,18 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
bool pbvh_bmesh_node_raycast(PBVHNode *node,
const float ray_start[3],
+ const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
float *depth,
- bool use_original)
+ bool use_original,
+ int *r_active_vertex_index,
+ float *r_face_normal)
{
bool hit = false;
+ float min_depth = FLT_MAX;
+ float nearest_vertex_co[3] = {0.0f};
+ float location[3] = {0.0f};
if (use_original && node->bm_tot_ortri) {
for (int i = 0; i < node->bm_tot_ortri; i++) {
const int *t = node->bm_ortri[i];
@@ -1538,6 +1544,19 @@ bool pbvh_bmesh_node_raycast(PBVHNode *node,
BM_face_as_array_vert_tri(f, v_tri);
hit |= ray_face_intersection_tri(
ray_start, isect_precalc, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co, depth);
+
+ if (hit && *depth < min_depth) {
+ min_depth = *depth;
+ normal_tri_v3(r_face_normal, v_tri[0]->co, v_tri[1]->co, v_tri[2]->co);
+ madd_v3_v3v3fl(location, ray_start, ray_normal, *depth);
+ for (int j = 0; j < 3; j++) {
+ if (len_squared_v3v3(location, v_tri[j]->co) <
+ len_squared_v3v3(location, nearest_vertex_co)) {
+ copy_v3_v3(nearest_vertex_co, v_tri[j]->co);
+ *r_active_vertex_index = BM_elem_index_get(v_tri[j]);
+ }
+ }
+ }
}
}
}
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index e74a8d43c68..bad103743eb 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -206,9 +206,12 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag);
/* pbvh_bmesh.c */
bool pbvh_bmesh_node_raycast(PBVHNode *node,
const float ray_start[3],
+ const float ray_normal[3],
struct IsectRayPrecalc *isect_precalc,
float *dist,
- bool use_original);
+ bool use_original,
+ int *r_active_vertex_index,
+ float *r_face_normal);
bool pbvh_bmesh_node_nearest_to_ray(PBVHNode *node,
const float ray_start[3],
const float ray_normal[3],
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 13d0f1adb84..a31cb96c6c9 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1831,6 +1831,10 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->file_type = PTCACHE_FILE_PTCACHE;
}
+/**
+ * \param ob: Optional, may be NULL.
+ * \param scene: Optional may be NULL.
+ */
PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache)
{
PTCacheID result = {0};
@@ -1934,40 +1938,45 @@ static bool foreach_object_ptcache(
Scene *scene, Object *object, int duplis, ForeachPtcacheCb callback, void *callback_user_data)
{
PTCacheID pid;
- /* Soft body. */
- if (object->soft != NULL) {
- BKE_ptcache_id_from_softbody(&pid, object, object->soft);
- if (!callback(&pid, callback_user_data)) {
+
+ if (object != NULL) {
+ /* Soft body. */
+ if (object->soft != NULL) {
+ BKE_ptcache_id_from_softbody(&pid, object, object->soft);
+ if (!callback(&pid, callback_user_data)) {
+ return false;
+ }
+ }
+ /* Particle systems. */
+ if (!foreach_object_particle_ptcache(object, callback, callback_user_data)) {
return false;
}
+ /* Modifiers. */
+ if (!foreach_object_modifier_ptcache(object, callback, callback_user_data)) {
+ return false;
+ }
+ /* Consider all object in dupli groups to be part of the same object,
+ * for baking with linking dupligroups. Once we have better overrides
+ * this can be revisited so users select the local objects directly. */
+ if (scene != NULL && (duplis-- > 0) && (object->instance_collection != NULL)) {
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (object->instance_collection, current_object) {
+ if (current_object == object) {
+ continue;
+ }
+ foreach_object_ptcache(scene, current_object, duplis, callback, callback_user_data);
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ }
}
- /* Particle systems. */
- if (!foreach_object_particle_ptcache(object, callback, callback_user_data)) {
- return false;
- }
- /* Modifiers. */
- if (!foreach_object_modifier_ptcache(object, callback, callback_user_data)) {
- return false;
- }
+
/* Rigid body. */
- if (scene != NULL && object->rigidbody_object != NULL && scene->rigidbody_world != NULL) {
+ if (scene != NULL && (object == NULL || object->rigidbody_object != NULL) &&
+ scene->rigidbody_world != NULL) {
BKE_ptcache_id_from_rigidbody(&pid, object, scene->rigidbody_world);
if (!callback(&pid, callback_user_data)) {
return false;
}
}
- /* Consider all object in dupli groups to be part of the same object,
- * for baking with linking dupligroups. Once we have better overrides
- * this can be revisited so users select the local objects directly. */
- if (scene != NULL && (duplis-- > 0) && (object->instance_collection != NULL)) {
- FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (object->instance_collection, current_object) {
- if (current_object == object) {
- continue;
- }
- foreach_object_ptcache(scene, current_object, duplis, callback, callback_user_data);
- }
- FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- }
return true;
}
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index ec73406c14c..514f000d73d 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -1452,7 +1452,7 @@ void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob)
/* Some users seems to find it funny to use a view-layer instancing collection
* as RBW collection... Despite this being a bad (ab)use of the system, avoid losing objects
* when we remove them from RB simulation. */
- BKE_collection_object_add(bmain, BKE_collection_master(scene), ob);
+ BKE_collection_object_add(bmain, scene->master_collection, ob);
}
BKE_collection_object_remove(bmain, rbw->group, ob, false);
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 3440c8dfb69..c4ce0cf6ed7 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -266,6 +266,8 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
{
/* We never handle usercount here for own data. */
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+ /* We always need allocation of our private ID data. */
+ const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE;
sce_dst->ed = NULL;
sce_dst->depsgraph_hash = NULL;
@@ -273,8 +275,10 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
/* Master Collection */
if (sce_src->master_collection) {
- sce_dst->master_collection = BKE_collection_copy_master(
- bmain, sce_src->master_collection, flag);
+ BKE_id_copy_ex(bmain,
+ (ID *)sce_src->master_collection,
+ (ID **)&sce_dst->master_collection,
+ flag_private_id_data);
}
/* View Layers */
@@ -292,10 +296,13 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
BKE_keyingsets_copy(&(sce_dst->keyingsets), &(sce_src->keyingsets));
if (sce_src->nodetree) {
- /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level
- * (see BKE_libblock_copy_ex()). */
- BKE_id_copy_ex(bmain, (ID *)sce_src->nodetree, (ID **)&sce_dst->nodetree, flag);
- BKE_libblock_relink_ex(bmain, sce_dst->nodetree, (void *)(&sce_src->id), &sce_dst->id, false);
+ BKE_id_copy_ex(
+ bmain, (ID *)sce_src->nodetree, (ID **)&sce_dst->nodetree, flag_private_id_data);
+ BKE_libblock_relink_ex(bmain,
+ sce_dst->nodetree,
+ (void *)(&sce_src->id),
+ &sce_dst->id,
+ ID_REMAP_SKIP_NEVER_NULL_USAGE);
}
if (sce_src->rigidbody_world) {
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index b151bc7f092..89f3f9ef9fd 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -1646,7 +1646,7 @@ static void do_blend_effect_float(
case SEQ_TYPE_DARKEN:
apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_float);
break;
- case SEQ_TYPE_BURN:
+ case SEQ_TYPE_COLOR_BURN:
apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_float);
break;
case SEQ_TYPE_LINEAR_BURN:
@@ -1734,7 +1734,7 @@ static void do_blend_effect_byte(float facf0,
case SEQ_TYPE_DARKEN:
apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_byte);
break;
- case SEQ_TYPE_BURN:
+ case SEQ_TYPE_COLOR_BURN:
apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_byte);
break;
case SEQ_TYPE_LINEAR_BURN:
@@ -4130,7 +4130,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
break;
case SEQ_TYPE_SCREEN:
case SEQ_TYPE_OVERLAY:
- case SEQ_TYPE_BURN:
+ case SEQ_TYPE_COLOR_BURN:
case SEQ_TYPE_LINEAR_BURN:
case SEQ_TYPE_DARKEN:
case SEQ_TYPE_LIGHTEN:
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 20736e28a53..d3b72fb295d 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -2705,7 +2705,7 @@ static void mesh_to_softbody(Scene *scene, Object *ob)
for (a = 0; a < me->totvert; a++, bp++) {
/* get scalar values needed *per vertex* from vertex group functions,
- * so we can *paint* them nicly ..
+ * so we can *paint* them nicely ..
* they are normalized [0.0..1.0] so may be we need amplitude for scale
* which can be done by caller but still .. i'd like it to go this way
*/
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index 6e83f5d75e2..b3f2a624ebe 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -46,13 +46,16 @@
#include "MEM_guardedalloc.h"
+#include "intern/openexr/openexr_multi.h"
+
/* Statics */
static ListBase studiolights;
static int last_studiolight_id = 0;
#define STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE 96
#define STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT 32
#define STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH (STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT * 2)
-
+#define STUDIOLIGHT_PASSNAME_DIFFUSE "diffuse"
+#define STUDIOLIGHT_PASSNAME_SPECULAR "specular"
/*
* The method to calculate the irradiance buffers
* The irradiance buffer is only shown in the background when in LookDev.
@@ -152,6 +155,10 @@ static void studiolight_free(struct StudioLight *sl)
GPU_TEXTURE_SAFE_FREE(sl->equirect_irradiance_gputexture);
IMB_SAFE_FREE(sl->equirect_radiance_buffer);
IMB_SAFE_FREE(sl->equirect_irradiance_buffer);
+ GPU_TEXTURE_SAFE_FREE(sl->matcap_diffuse.gputexture);
+ GPU_TEXTURE_SAFE_FREE(sl->matcap_specular.gputexture);
+ IMB_SAFE_FREE(sl->matcap_diffuse.ibuf);
+ IMB_SAFE_FREE(sl->matcap_specular.ibuf);
MEM_SAFE_FREE(sl->path_irr_cache);
MEM_SAFE_FREE(sl->path_sh_cache);
MEM_SAFE_FREE(sl);
@@ -342,72 +349,232 @@ static void cube_face_uv_to_direction(float r_dir[3], float x, float y, int face
normalize_v3(r_dir);
}
+typedef struct MultilayerConvertContext {
+ int num_diffuse_channels;
+ float *diffuse_pass;
+ int num_specular_channels;
+ float *specular_pass;
+} MultilayerConvertContext;
+
+static void *studiolight_multilayer_addview(void *UNUSED(base), const char *UNUSED(view_name))
+{
+ return NULL;
+}
+static void *studiolight_multilayer_addlayer(void *base, const char *UNUSED(layer_name))
+{
+ return base;
+}
+
+/* Convert a multilayer pass to ImBuf channel 4 float buffer.
+ * NOTE: Parameter rect will become invalid. Do not use rect after calling this
+ * function */
+static float *studiolight_multilayer_convert_pass(ImBuf *ibuf,
+ float *rect,
+ const unsigned int channels)
+{
+ if (channels == 4) {
+ return rect;
+ }
+ else {
+ float *new_rect = MEM_callocN(sizeof(float[4]) * ibuf->x * ibuf->y, __func__);
+
+ IMB_buffer_float_from_float(new_rect,
+ rect,
+ channels,
+ IB_PROFILE_LINEAR_RGB,
+ IB_PROFILE_LINEAR_RGB,
+ false,
+ ibuf->x,
+ ibuf->y,
+ ibuf->x,
+ ibuf->x);
+
+ MEM_freeN(rect);
+ return new_rect;
+ }
+}
+
+static void studiolight_multilayer_addpass(void *base,
+ void *UNUSED(lay),
+ const char *pass_name,
+ float *rect,
+ int num_channels,
+ const char *UNUSED(chan_id),
+ const char *UNUSED(view_name))
+{
+ MultilayerConvertContext *ctx = base;
+ /* NOTE: This function must free pass pixels data if it is not used, this
+ * is how IMB_exr_multilayer_convert() is working. */
+ /* If we've found a first combined pass, skip all the rest ones. */
+ if (STREQ(pass_name, STUDIOLIGHT_PASSNAME_DIFFUSE)) {
+ ctx->diffuse_pass = rect;
+ ctx->num_diffuse_channels = num_channels;
+ }
+ else if (STREQ(pass_name, STUDIOLIGHT_PASSNAME_SPECULAR)) {
+ ctx->specular_pass = rect;
+ ctx->num_specular_channels = num_channels;
+ }
+ else {
+ MEM_freeN(rect);
+ }
+}
+
static void studiolight_load_equirect_image(StudioLight *sl)
{
if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
- ImBuf *ibuf = NULL;
- ibuf = IMB_loadiffname(sl->path, 0, NULL);
- if (ibuf == NULL) {
- float *colbuf = MEM_mallocN(sizeof(float[4]), __func__);
- copy_v4_fl4(colbuf, 1.0f, 0.0f, 1.0f, 1.0f);
- ibuf = IMB_allocFromBuffer(NULL, colbuf, 1, 1);
+ ImBuf *ibuf = IMB_loadiffname(sl->path, IB_multilayer, NULL);
+ ImBuf *specular_ibuf = NULL;
+ ImBuf *diffuse_ibuf = NULL;
+ const bool failed = (ibuf == NULL);
+
+ if (ibuf) {
+ if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
+ /* the read file is a multilayered openexr file (userdata != NULL)
+ * This file is currently only supported for MATCAPS where
+ * the first found 'diffuse' pass will be used for diffuse lighting
+ * and the first found 'specular' pass will be used for specular lighting */
+ MultilayerConvertContext ctx = {0};
+ IMB_exr_multilayer_convert(ibuf->userdata,
+ &ctx,
+ &studiolight_multilayer_addview,
+ &studiolight_multilayer_addlayer,
+ &studiolight_multilayer_addpass);
+
+ /* `ctx.diffuse_pass` and `ctx.specular_pass` can be freed inside
+ * `studiolight_multilayer_convert_pass` when conversion happens.
+ * When not converted we move the ownership of the buffer to the
+ * `converted_pass`. We only need to free `converted_pass` as it holds
+ * the unmodified allocation from the `ctx.*_pass` or the converted data.
+ */
+ if (ctx.diffuse_pass != NULL) {
+ float *converted_pass = studiolight_multilayer_convert_pass(
+ ibuf, ctx.diffuse_pass, ctx.num_diffuse_channels);
+ diffuse_ibuf = IMB_allocFromBuffer(
+ NULL, converted_pass, ibuf->x, ibuf->y, ctx.num_diffuse_channels);
+ MEM_freeN(converted_pass);
+ }
+
+ if (ctx.specular_pass != NULL) {
+ float *converted_pass = studiolight_multilayer_convert_pass(
+ ibuf, ctx.specular_pass, ctx.num_specular_channels);
+ specular_ibuf = IMB_allocFromBuffer(
+ NULL, converted_pass, ibuf->x, ibuf->y, ctx.num_specular_channels);
+ MEM_freeN(converted_pass);
+ }
+
+ IMB_exr_close(ibuf->userdata);
+ ibuf->userdata = NULL;
+ IMB_freeImBuf(ibuf);
+ ibuf = NULL;
+ }
+ else {
+ /* read file is an single layer openexr file or the read file isn't
+ * an openexr file */
+ IMB_float_from_rect(ibuf);
+ diffuse_ibuf = ibuf;
+ ibuf = NULL;
+ }
+ }
+
+ if (diffuse_ibuf == NULL) {
+ /* Create 1x1 diffuse buffer, in case image failed to load or if there was
+ * only a specular pass in the multilayer file or no passes were found. */
+ const float black[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ const float magenta[4] = {1.0f, 0.0f, 1.0f, 1.0f};
+ diffuse_ibuf = IMB_allocFromBuffer(
+ NULL, (failed || (specular_ibuf == NULL)) ? magenta : black, 1, 1, 4);
+ }
+
+ if ((sl->flag & STUDIOLIGHT_TYPE_MATCAP)) {
+ sl->matcap_diffuse.ibuf = diffuse_ibuf;
+ sl->matcap_specular.ibuf = specular_ibuf;
+ if (specular_ibuf != NULL) {
+ sl->flag |= STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS;
+ }
+ }
+ else {
+ sl->equirect_radiance_buffer = diffuse_ibuf;
+ if (specular_ibuf != NULL) {
+ IMB_freeImBuf(specular_ibuf);
+ }
}
- IMB_float_from_rect(ibuf);
- sl->equirect_radiance_buffer = ibuf;
}
+
sl->flag |= STUDIOLIGHT_EXTERNAL_IMAGE_LOADED;
}
static void studiolight_create_equirect_radiance_gputexture(StudioLight *sl)
{
if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
- char error[256];
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
ImBuf *ibuf = sl->equirect_radiance_buffer;
- if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) {
- float *gpu_matcap_3components = MEM_callocN(sizeof(float[3]) * ibuf->x * ibuf->y, __func__);
+ sl->equirect_radiance_gputexture = GPU_texture_create_2d(
+ ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL);
+ GPUTexture *tex = sl->equirect_radiance_gputexture;
+ GPU_texture_bind(tex, 0);
+ GPU_texture_filter_mode(tex, true);
+ GPU_texture_wrap_mode(tex, true);
+ GPU_texture_unbind(tex);
+ }
+ sl->flag |= STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE;
+}
- float(*offset4)[4] = (float(*)[4])ibuf->rect_float;
- float(*offset3)[3] = (float(*)[3])gpu_matcap_3components;
- for (int i = 0; i < ibuf->x * ibuf->y; i++, offset4++, offset3++) {
- copy_v3_v3(*offset3, *offset4);
- }
+static void studiolight_create_matcap_gputexture(StudioLightImage *sli)
+{
+ BLI_assert(sli->ibuf);
+ ImBuf *ibuf = sli->ibuf;
+ float *gpu_matcap_3components = MEM_callocN(sizeof(float[3]) * ibuf->x * ibuf->y, __func__);
+
+ float(*offset4)[4] = (float(*)[4])ibuf->rect_float;
+ float(*offset3)[3] = (float(*)[3])gpu_matcap_3components;
+ for (int i = 0; i < ibuf->x * ibuf->y; i++, offset4++, offset3++) {
+ copy_v3_v3(*offset3, *offset4);
+ }
+
+ sli->gputexture = GPU_texture_create_nD(ibuf->x,
+ ibuf->y,
+ 0,
+ 2,
+ gpu_matcap_3components,
+ GPU_R11F_G11F_B10F,
+ GPU_DATA_FLOAT,
+ 0,
+ false,
+ NULL);
+ MEM_SAFE_FREE(gpu_matcap_3components);
+}
- sl->equirect_radiance_gputexture = GPU_texture_create_nD(ibuf->x,
- ibuf->y,
- 0,
- 2,
- gpu_matcap_3components,
- GPU_R11F_G11F_B10F,
- GPU_DATA_FLOAT,
- 0,
- false,
- error);
-
- MEM_SAFE_FREE(gpu_matcap_3components);
+static void studiolight_create_matcap_diffuse_gputexture(StudioLight *sl)
+{
+ if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
+ if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) {
+ BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
+ studiolight_create_matcap_gputexture(&sl->matcap_diffuse);
}
- else {
- sl->equirect_radiance_gputexture = GPU_texture_create_2d(
- ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error);
- GPUTexture *tex = sl->equirect_radiance_gputexture;
- GPU_texture_bind(tex, 0);
- GPU_texture_filter_mode(tex, true);
- GPU_texture_wrap_mode(tex, true);
- GPU_texture_unbind(tex);
+ }
+ sl->flag |= STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE;
+}
+static void studiolight_create_matcap_specular_gputexture(StudioLight *sl)
+{
+ if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
+ if (sl->flag & STUDIOLIGHT_TYPE_MATCAP) {
+ BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
+ if (sl->matcap_specular.ibuf) {
+ studiolight_create_matcap_gputexture(&sl->matcap_specular);
+ }
}
}
- sl->flag |= STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE;
+ sl->flag |= STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE;
}
static void studiolight_create_equirect_irradiance_gputexture(StudioLight *sl)
{
if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
- char error[256];
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EQUIRECT_IRRADIANCE_IMAGE_CALCULATED);
ImBuf *ibuf = sl->equirect_irradiance_buffer;
sl->equirect_irradiance_gputexture = GPU_texture_create_2d(
- ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, error);
+ ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL);
GPUTexture *tex = sl->equirect_irradiance_gputexture;
GPU_texture_bind(tex, 0);
GPU_texture_filter_mode(tex, true);
@@ -457,32 +624,32 @@ static void studiolight_calculate_radiance_cubemap_buffers(StudioLight *sl)
/* front */
studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 2, 1, 1, -1, 1);
sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS] = IMB_allocFromBuffer(
- NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
+ NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
/* back */
studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 2, 1, 1, 1, -1);
sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG] = IMB_allocFromBuffer(
- NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
+ NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
/* left */
studiolight_calculate_radiance_buffer(ibuf, colbuf, 2, 1, 0, 1, -1, 1);
sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS] = IMB_allocFromBuffer(
- NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
+ NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
/* right */
studiolight_calculate_radiance_buffer(ibuf, colbuf, 2, 1, 0, -1, -1, -1);
sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG] = IMB_allocFromBuffer(
- NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
+ NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
/* top */
studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 1, 2, -1, -1, 1);
sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG] = IMB_allocFromBuffer(
- NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
+ NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
/* bottom */
studiolight_calculate_radiance_buffer(ibuf, colbuf, 0, 1, 2, 1, -1, -1);
sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS] = IMB_allocFromBuffer(
- NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
+ NULL, colbuf, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE, 4);
#if 0
IMB_saveiff(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS],
@@ -603,7 +770,8 @@ static void studiolight_spherical_harmonics_calculate_coefficients(StudioLight *
/* Take monochrome SH as input */
static float studiolight_spherical_harmonics_lambda_get(float *sh, float max_laplacian)
{
- /* From Peter-Pike Sloan's Stupid SH Tricks http://www.ppsloan.org/publications/StupidSH36.pdf */
+ /* From Peter-Pike Sloan's Stupid SH Tricks http://www.ppsloan.org/publications/StupidSH36.pdf
+ */
float table_l[STUDIOLIGHT_SH_BANDS];
float table_b[STUDIOLIGHT_SH_BANDS];
@@ -720,7 +888,6 @@ BLI_INLINE void studiolight_spherical_harmonics_eval(StudioLight *sl,
}
return;
#else
-
/* L0 */
mul_v3_v3fl(color, sl->spherical_harmonics_coefs[0], 0.282095f);
# if STUDIOLIGHT_SH_BANDS > 1 /* L1 */
@@ -1045,7 +1212,8 @@ static void studiolight_calculate_irradiance_equirect_image(StudioLight *sl)
sl->equirect_irradiance_buffer = IMB_allocFromBuffer(NULL,
colbuf,
STUDIOLIGHT_IRRADIANCE_EQUIRECT_WIDTH,
- STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT);
+ STUDIOLIGHT_IRRADIANCE_EQUIRECT_HEIGHT,
+ 4);
MEM_freeN(colbuf);
#ifdef STUDIOLIGHT_IRRADIANCE_METHOD_RADIANCE
@@ -1196,7 +1364,8 @@ static void studiolight_matcap_preview(uint *icon_buffer, StudioLight *sl, bool
{
BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_EXTERNAL_IMAGE_LOADED);
- ImBuf *ibuf = sl->equirect_radiance_buffer;
+ ImBuf *diffuse_buffer = sl->matcap_diffuse.ibuf;
+ ImBuf *specular_buffer = sl->matcap_specular.ibuf;
ITER_PIXELS (uint, icon_buffer, 1, STUDIOLIGHT_ICON_SIZE, STUDIOLIGHT_ICON_SIZE) {
float dy = RESCALE_COORD(y);
@@ -1206,7 +1375,15 @@ static void studiolight_matcap_preview(uint *icon_buffer, StudioLight *sl, bool
}
float color[4];
- nearest_interpolation_color(ibuf, NULL, color, dx * ibuf->x - 1.0f, dy * ibuf->y - 1.0f);
+ float u = dx * diffuse_buffer->x - 1.0f;
+ float v = dy * diffuse_buffer->y - 1.0f;
+ nearest_interpolation_color(diffuse_buffer, NULL, color, u, v);
+
+ if (specular_buffer) {
+ float specular[4];
+ nearest_interpolation_color(specular_buffer, NULL, specular, u, v);
+ add_v3_v3(color, specular);
+ }
uint alphamask = alpha_circle_mask(dx, dy, 0.5f - texel_size[0], 0.5f);
@@ -1303,9 +1480,9 @@ void BKE_studiolight_default(SolidLight lights[4], float light_ambient[4])
void BKE_studiolight_init(void)
{
/* Add default studio light */
- StudioLight *sl = studiolight_create(STUDIOLIGHT_INTERNAL |
- STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED |
- STUDIOLIGHT_TYPE_STUDIO);
+ StudioLight *sl = studiolight_create(
+ STUDIOLIGHT_INTERNAL | STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED |
+ STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS);
BLI_strncpy(sl->name, "Default", FILE_MAXFILE);
BLI_addtail(&studiolights, sl);
@@ -1317,7 +1494,8 @@ void BKE_studiolight_init(void)
if (!BKE_appdir_app_is_portable_install()) {
studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES,
STUDIOLIGHT_LIGHTS_FOLDER,
- STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_USER_DEFINED);
+ STUDIOLIGHT_TYPE_STUDIO | STUDIOLIGHT_USER_DEFINED |
+ STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS);
studiolight_add_files_from_datafolder(BLENDER_USER_DATAFILES,
STUDIOLIGHT_WORLD_FOLDER,
STUDIOLIGHT_TYPE_WORLD | STUDIOLIGHT_USER_DEFINED);
@@ -1325,8 +1503,10 @@ void BKE_studiolight_init(void)
STUDIOLIGHT_MATCAP_FOLDER,
STUDIOLIGHT_TYPE_MATCAP | STUDIOLIGHT_USER_DEFINED);
}
- studiolight_add_files_from_datafolder(
- BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_LIGHTS_FOLDER, STUDIOLIGHT_TYPE_STUDIO);
+ studiolight_add_files_from_datafolder(BLENDER_SYSTEM_DATAFILES,
+ STUDIOLIGHT_LIGHTS_FOLDER,
+ STUDIOLIGHT_TYPE_STUDIO |
+ STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS);
studiolight_add_files_from_datafolder(
BLENDER_SYSTEM_DATAFILES, STUDIOLIGHT_WORLD_FOLDER, STUDIOLIGHT_TYPE_WORLD);
studiolight_add_files_from_datafolder(
@@ -1456,6 +1636,12 @@ void BKE_studiolight_ensure_flag(StudioLight *sl, int flag)
studiolight_calculate_irradiance_equirect_image(sl);
}
}
+ if ((flag & STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE)) {
+ studiolight_create_matcap_diffuse_gputexture(sl);
+ }
+ if ((flag & STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE)) {
+ studiolight_create_matcap_specular_gputexture(sl);
+ }
}
/*
diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c
index 1ff9140681f..9d713d1937d 100644
--- a/source/blender/blenkernel/intern/subdiv_mesh.c
+++ b/source/blender/blenkernel/intern/subdiv_mesh.c
@@ -498,9 +498,14 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex
const int num_loops,
const int num_polygons)
{
+ /* Multires grid data will be applied or become invalid after subdivision,
+ * so don't try to preserve it and use memory. */
+ CustomData_MeshMasks mask = CD_MASK_EVERYTHING;
+ mask.lmask &= ~CD_MASK_MULTIRES_GRIDS;
+
SubdivMeshContext *subdiv_context = foreach_context->user_data;
- subdiv_context->subdiv_mesh = BKE_mesh_new_nomain_from_template(
- subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_loops, num_polygons);
+ subdiv_context->subdiv_mesh = BKE_mesh_new_nomain_from_template_ex(
+ subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_loops, num_polygons, mask);
subdiv_mesh_ctx_cache_custom_data_layers(subdiv_context);
subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices);
return true;
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 3f57ae169ff..77dc438cd04 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -83,8 +83,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss,
int useSubsurfUv,
DerivedMesh *dm,
bool use_gpu_backend);
-static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm);
-
///
static void *arena_alloc(CCGAllocatorHDL a, int numBytes)
@@ -1580,221 +1578,6 @@ static void ccgDM_copyFinalPolyArray(DerivedMesh *dm, MPoly *mpoly)
}
}
-static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3])
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
- CCGSubSurf *ss = ccgdm->ss;
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
- int gridSize = ccgSubSurf_getGridSize(ss);
- int i;
- CCGVertIterator vi;
- CCGEdgeIterator ei;
- CCGFaceIterator fi;
- CCGFace **faceMap2;
- CCGEdge **edgeMap2;
- CCGVert **vertMap2;
- int index, totvert, totedge, totface;
-
- totvert = ccgSubSurf_getNumVerts(ss);
- vertMap2 = MEM_mallocN(totvert * sizeof(*vertMap2), "vertmap");
- for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi);
- ccgVertIterator_next(&vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(&vi);
-
- vertMap2[POINTER_AS_INT(ccgSubSurf_getVertVertHandle(v))] = v;
- }
-
- totedge = ccgSubSurf_getNumEdges(ss);
- edgeMap2 = MEM_mallocN(totedge * sizeof(*edgeMap2), "edgemap");
- for (ccgSubSurf_initEdgeIterator(ss, &ei), i = 0; !ccgEdgeIterator_isStopped(&ei);
- i++, ccgEdgeIterator_next(&ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
-
- edgeMap2[POINTER_AS_INT(ccgSubSurf_getEdgeEdgeHandle(e))] = e;
- }
-
- totface = ccgSubSurf_getNumFaces(ss);
- faceMap2 = MEM_mallocN(totface * sizeof(*faceMap2), "facemap");
- for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi);
- ccgFaceIterator_next(&fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(&fi);
-
- faceMap2[POINTER_AS_INT(ccgSubSurf_getFaceFaceHandle(f))] = f;
- }
-
- i = 0;
- for (index = 0; index < totface; index++) {
- CCGFace *f = faceMap2[index];
- int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
-
- copy_v3_v3(cos[i++], ccgSubSurf_getFaceCenterData(f));
-
- for (S = 0; S < numVerts; S++) {
- for (x = 1; x < gridSize - 1; x++) {
- copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridEdgeData(ss, f, S, x));
- }
- }
-
- for (S = 0; S < numVerts; S++) {
- for (y = 1; y < gridSize - 1; y++) {
- for (x = 1; x < gridSize - 1; x++) {
- copy_v3_v3(cos[i++], ccgSubSurf_getFaceGridData(ss, f, S, x, y));
- }
- }
- }
- }
-
- for (index = 0; index < totedge; index++) {
- CCGEdge *e = edgeMap2[index];
- int x;
-
- for (x = 1; x < edgeSize - 1; x++) {
- copy_v3_v3(cos[i++], ccgSubSurf_getEdgeData(ss, e, x));
- }
- }
-
- for (index = 0; index < totvert; index++) {
- CCGVert *v = vertMap2[index];
- copy_v3_v3(cos[i++], ccgSubSurf_getVertData(ss, v));
- }
-
- MEM_freeN(vertMap2);
- MEM_freeN(edgeMap2);
- MEM_freeN(faceMap2);
-}
-
-static void ccgDM_foreachMappedVert(DerivedMesh *dm,
- void (*func)(void *userData,
- int index,
- const float co[3],
- const float no_f[3],
- const short no_s[3]),
- void *userData,
- DMForeachFlag flag)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
- CCGVertIterator vi;
- CCGKey key;
- CCG_key_top_level(&key, ccgdm->ss);
-
- for (ccgSubSurf_initVertIterator(ccgdm->ss, &vi); !ccgVertIterator_isStopped(&vi);
- ccgVertIterator_next(&vi)) {
- CCGVert *v = ccgVertIterator_getCurrent(&vi);
- const int index = ccgDM_getVertMapIndex(ccgdm->ss, v);
-
- if (index != -1) {
- CCGElem *vd = ccgSubSurf_getVertData(ccgdm->ss, v);
- const float *no = (flag & DM_FOREACH_USE_NORMAL) ? CCG_elem_no(&key, vd) : NULL;
- func(userData, index, CCG_elem_co(&key, vd), no, NULL);
- }
- }
-}
-
-static void ccgDM_foreachMappedEdge(
- DerivedMesh *dm,
- void (*func)(void *userData, int index, const float v0co[3], const float v1co[3]),
- void *userData)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGEdgeIterator ei;
- CCGKey key;
- int i, edgeSize = ccgSubSurf_getEdgeSize(ss);
-
- CCG_key_top_level(&key, ss);
-
- for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei);
- ccgEdgeIterator_next(&ei)) {
- CCGEdge *e = ccgEdgeIterator_getCurrent(&ei);
- const int index = ccgDM_getEdgeMapIndex(ss, e);
-
- if (index != -1) {
- CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e);
- for (i = 0; i < edgeSize - 1; i++) {
- func(userData,
- index,
- CCG_elem_offset_co(&key, edgeData, i),
- CCG_elem_offset_co(&key, edgeData, i + 1));
- }
- }
- }
-}
-
-static void ccgDM_foreachMappedLoop(DerivedMesh *dm,
- void (*func)(void *userData,
- int vertex_index,
- int face_index,
- const float co[3],
- const float no[3]),
- void *userData,
- DMForeachFlag flag)
-{
- /* We can't use dm->getLoopDataLayout(dm) here, we want to always access dm->loopData,
- * EditDerivedBMesh would return loop data from bmesh itself. */
- const float(*lnors)[3] = (flag & DM_FOREACH_USE_NORMAL) ? DM_get_loop_data_layer(dm, CD_NORMAL) :
- NULL;
-
- MVert *mv = dm->getVertArray(dm);
- MLoop *ml = dm->getLoopArray(dm);
- MPoly *mp = dm->getPolyArray(dm);
- const int *v_index = dm->getVertDataArray(dm, CD_ORIGINDEX);
- const int *f_index = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- int p_idx, i;
-
- for (p_idx = 0; p_idx < dm->numPolyData; ++p_idx, ++mp) {
- for (i = 0; i < mp->totloop; ++i, ++ml) {
- const int v_idx = v_index ? v_index[ml->v] : ml->v;
- const int f_idx = f_index ? f_index[p_idx] : p_idx;
- const float *no = lnors ? *lnors++ : NULL;
- if (!ELEM(ORIGINDEX_NONE, v_idx, f_idx)) {
- func(userData, v_idx, f_idx, mv[ml->v].co, no);
- }
- }
- }
-}
-
-static void UNUSED_FUNCTION(ccgdm_pbvh_update)(CCGDerivedMesh *ccgdm)
-{
- if (ccgdm->pbvh && ccgDM_use_grid_pbvh(ccgdm)) {
- CCGFace **faces;
- int totface;
-
- BKE_pbvh_get_grid_updates(ccgdm->pbvh, 1, (void ***)&faces, &totface);
- if (totface) {
- ccgSubSurf_updateFromFaces(ccgdm->ss, 0, faces, totface);
- ccgSubSurf_updateNormals(ccgdm->ss, faces, totface);
- MEM_freeN(faces);
- }
- }
-}
-
-static void ccgDM_foreachMappedFaceCenter(
- DerivedMesh *dm,
- void (*func)(void *userData, int index, const float co[3], const float no[3]),
- void *userData,
- DMForeachFlag flag)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGKey key;
- CCGFaceIterator fi;
-
- CCG_key_top_level(&key, ss);
-
- for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi);
- ccgFaceIterator_next(&fi)) {
- CCGFace *f = ccgFaceIterator_getCurrent(&fi);
- const int index = ccgDM_getFaceMapIndex(ss, f);
-
- if (index != -1) {
- /* Face center data normal isn't updated atm. */
- CCGElem *vd = ccgSubSurf_getFaceGridData(ss, f, 0, 0, 0);
- const float *no = (flag & DM_FOREACH_USE_NORMAL) ? CCG_elem_no(&key, vd) : NULL;
- func(userData, index, CCG_elem_co(&key, vd), no);
- }
- }
-}
-
static void ccgDM_release(DerivedMesh *dm)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
@@ -2222,174 +2005,6 @@ static const MeshElemMap *ccgDM_getPolyMap(Object *ob, DerivedMesh *dm)
return ccgdm->pmap;
}
-static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm)
-{
- MultiresModifierData *mmd = ccgdm->multires.mmd;
-
- /* both of multires and subsurf modifiers are CCG, but
- * grids should only be used when sculpting on multires */
- if (!mmd) {
- return 0;
- }
-
- return 1;
-}
-
-static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
- CCGKey key;
- int numGrids;
-
- CCG_key_top_level(&key, ccgdm->ss);
-
- if (!ob) {
- ccgdm->pbvh = NULL;
- return NULL;
- }
-
- if (!ob->sculpt) {
- return NULL;
- }
-
- bool grid_pbvh = ccgDM_use_grid_pbvh(ccgdm);
- if ((ob->mode & OB_MODE_SCULPT) == 0) {
- /* In vwpaint, we may use a grid_pbvh for multires/subsurf, under certain conditions.
- * More complex cases break 'history' trail back to original vertices,
- * in that case we fall back to deformed cage only (i.e. original deformed mesh). */
- VirtualModifierData virtualModifierData;
- ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
-
- grid_pbvh = true;
- bool has_one_ccg_modifier = false;
- for (; md; md = md->next) {
- /* We can only accept to use this ccgdm if:
- * - it's the only active ccgdm in the stack.
- * - there is no topology-modifying modifier in the stack.
- * Otherwise, there is no way to map back to original geometry from grid-generated PBVH.
- */
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (!modifier_isEnabled(NULL, md, eModifierMode_Realtime)) {
- continue;
- }
- if (ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical)) {
- continue;
- }
-
- if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) {
- if (has_one_ccg_modifier) {
- /* We only allow a single active ccg modifier in the stack. */
- grid_pbvh = false;
- break;
- }
- has_one_ccg_modifier = true;
- continue;
- }
-
- /* Any other non-deforming modifier makes it impossible to use grid pbvh. */
- grid_pbvh = false;
- break;
- }
- }
-
- if (ob->sculpt->pbvh) {
- /* Note that we have to clean up existing pbvh instead of updating it in case it does not
- * match current grid_pbvh status. */
- const PBVHType pbvh_type = BKE_pbvh_type(ob->sculpt->pbvh);
- if (grid_pbvh) {
- if (pbvh_type == PBVH_GRIDS) {
- /* pbvh's grids, gridadj and gridfaces points to data inside ccgdm
- * but this can be freed on ccgdm release, this updates the pointers
- * when the ccgdm gets remade, the assumption is that the topology
- * does not change. */
- ccgdm_create_grids(dm);
- BKE_pbvh_grids_update(ob->sculpt->pbvh,
- ccgdm->gridData,
- (void **)ccgdm->gridFaces,
- ccgdm->gridFlagMats,
- ccgdm->gridHidden);
- }
- else {
- BKE_pbvh_free(ob->sculpt->pbvh);
- ob->sculpt->pbvh = NULL;
- }
- }
- else if (pbvh_type == PBVH_GRIDS) {
- BKE_pbvh_free(ob->sculpt->pbvh);
- ob->sculpt->pbvh = NULL;
- }
-
- ccgdm->pbvh = ob->sculpt->pbvh;
- }
-
- if (ccgdm->pbvh) {
- return ccgdm->pbvh;
- }
-
- /* No pbvh exists yet, we need to create one. only in case of multires
- * we build a pbvh over the modified mesh, in other cases the base mesh
- * is being sculpted, so we build a pbvh from that. */
- /* Note: vwpaint tries to always build a pbvh over the modified mesh. */
- if (grid_pbvh) {
- ccgdm_create_grids(dm);
-
- numGrids = ccgDM_getNumGrids(dm);
-
- ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
- BKE_pbvh_build_grids(ccgdm->pbvh,
- ccgdm->gridData,
- numGrids,
- &key,
- (void **)ccgdm->gridFaces,
- ccgdm->gridFlagMats,
- ccgdm->gridHidden);
- }
- else if (ob->type == OB_MESH) {
- Mesh *me = BKE_object_get_original_mesh(ob);
- const int looptris_num = poly_to_tri_count(me->totpoly, me->totloop);
- MLoopTri *looptri;
-
- looptri = MEM_mallocN(sizeof(*looptri) * looptris_num, __func__);
-
- BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, looptri);
-
- ob->sculpt->pbvh = ccgdm->pbvh = BKE_pbvh_new();
- BKE_pbvh_build_mesh(ccgdm->pbvh,
- me->mpoly,
- me->mloop,
- me->mvert,
- me->totvert,
- &me->vdata,
- &me->ldata,
- looptri,
- looptris_num);
-
- if (ob->sculpt->modifiers_active && ob->derivedDeform != NULL) {
- DerivedMesh *deformdm = ob->derivedDeform;
- float(*vertCos)[3];
- int totvert;
-
- totvert = deformdm->getNumVerts(deformdm);
- vertCos = MEM_malloc_arrayN(totvert, sizeof(float[3]), "ccgDM_getPBVH vertCos");
- deformdm->getVertCos(deformdm, vertCos);
- BKE_pbvh_apply_vertCos(ccgdm->pbvh, vertCos, totvert);
- MEM_freeN(vertCos);
- }
- }
-
- if (ccgdm->pbvh != NULL) {
- pbvh_show_mask_set(ccgdm->pbvh, ob->sculpt->show_mask);
- }
-
- return ccgdm->pbvh;
-}
-
-static void ccgDM_recalcTessellation(DerivedMesh *UNUSED(dm))
-{
- /* Nothing to do: CCG handles creating its own tessfaces */
-}
-
/* WARNING! *MUST* be called in an 'loops_cache_rwlock' protected thread context! */
static void ccgDM_recalcLoopTri(DerivedMesh *dm)
{
@@ -2425,12 +2040,6 @@ static void ccgDM_recalcLoopTri(DerivedMesh *dm)
dm->looptris.array_wip = NULL;
}
-static void ccgDM_calcNormals(DerivedMesh *dm)
-{
- /* Nothing to do: CCG calculates normals during drawing */
- dm->dirty &= ~DM_DIRTY_NORMALS;
-}
-
static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
{
ccgdm->dm.getMinMax = ccgDM_getMinMax;
@@ -2471,21 +2080,9 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
ccgdm->dm.getGridFlagMats = ccgDM_getGridFlagMats;
ccgdm->dm.getGridHidden = ccgDM_getGridHidden;
ccgdm->dm.getPolyMap = ccgDM_getPolyMap;
- ccgdm->dm.getPBVH = ccgDM_getPBVH;
- ccgdm->dm.calcNormals = ccgDM_calcNormals;
- ccgdm->dm.calcLoopNormals = CDDM_calc_loop_normals;
- ccgdm->dm.calcLoopNormalsSpaceArray = CDDM_calc_loop_normals_spacearr;
- ccgdm->dm.calcLoopTangents = DM_calc_loop_tangents;
- ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation;
ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri;
- ccgdm->dm.getVertCos = ccgdm_getVertCos;
- ccgdm->dm.foreachMappedVert = ccgDM_foreachMappedVert;
- ccgdm->dm.foreachMappedEdge = ccgDM_foreachMappedEdge;
- ccgdm->dm.foreachMappedLoop = ccgDM_foreachMappedLoop;
- ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter;
-
ccgdm->dm.release = ccgDM_release;
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index ad7c5e3f660..5c03b7730aa 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -423,6 +423,11 @@ MTex *BKE_texture_mtex_add_id(ID *id, int slot)
*/
void BKE_texture_copy_data(Main *bmain, Tex *tex_dst, const Tex *tex_src, const int flag)
{
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+ /* We always need allocation of our private ID data. */
+ const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE;
+
if (!BKE_texture_is_image_user(tex_src)) {
tex_dst->ima = NULL;
}
@@ -434,9 +439,8 @@ void BKE_texture_copy_data(Main *bmain, Tex *tex_dst, const Tex *tex_src, const
if (tex_src->nodetree->execdata) {
ntreeTexEndExecTree(tex_src->nodetree->execdata);
}
- /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level
- * (see BKE_libblock_copy_ex()). */
- BKE_id_copy_ex(bmain, (ID *)tex_src->nodetree, (ID **)&tex_dst->nodetree, flag);
+ BKE_id_copy_ex(
+ bmain, (ID *)tex_src->nodetree, (ID **)&tex_dst->nodetree, flag_private_id_data);
}
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c
index 7e7a839b645..ab741eed410 100644
--- a/source/blender/blenkernel/intern/tracking_solver.c
+++ b/source/blender/blenkernel/intern/tracking_solver.c
@@ -221,7 +221,7 @@ static bool reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context,
*
* There's one weak part tho, which is requirement object
* motion starts at the same frame as camera motion does,
- * otherwise that;' be a russian roulette whether object is
+ * otherwise that;' be a Russian roulette whether object is
* aligned correct or not.
*/
if (!origin_set) {
diff --git a/source/blender/blenkernel/intern/tracking_stabilize.c b/source/blender/blenkernel/intern/tracking_stabilize.c
index 03229c654fb..7da36ba9af9 100644
--- a/source/blender/blenkernel/intern/tracking_stabilize.c
+++ b/source/blender/blenkernel/intern/tracking_stabilize.c
@@ -1129,8 +1129,8 @@ static void stabilization_data_to_mat4(float pixel_aspect,
}
/* Calculate scale factor necessary to eliminate black image areas
- * caused by the compensating movements of the stabilizator.
- * This function visits every frame where stabilisation data is
+ * caused by the compensating movements of the stabilizer.
+ * This function visits every frame where stabilization data is
* available and determines the factor for this frame. The overall
* largest factor found is returned as result.
*
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
index 07cf5205cab..36b950fb8f9 100644
--- a/source/blender/blenkernel/intern/undo_system.c
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -503,7 +503,7 @@ bool BKE_undosys_step_push_with_type(UndoStack *ustack,
/* Might not be final place for this to be called - probably only want to call it from some
* undo handlers, not all of them? */
if (BKE_override_library_is_enabled()) {
- BKE_main_override_library_operations_create(G.main, false);
+ BKE_main_override_library_operations_create(CTX_data_main(C), false);
}
/* Remove all undos after (also when 'ustack->step_active == NULL'). */
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index e30ea687b13..ac1b5e4ab0b 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -501,12 +501,12 @@ static PreferredUnits preferred_units_from_UnitSettings(const UnitSettings *sett
return units;
}
-static size_t unit_as_string_splitted(char *str,
- int len_max,
- double value,
- int prec,
- const bUnitCollection *usys,
- const bUnitDef *main_unit)
+static size_t unit_as_string_split_pair(char *str,
+ int len_max,
+ double value,
+ int prec,
+ const bUnitCollection *usys,
+ const bUnitDef *main_unit)
{
const bUnitDef *unit_a, *unit_b;
double value_a, value_b;
@@ -602,7 +602,7 @@ static size_t unit_as_string_main(char *str,
}
if (split && unit_should_be_split(type)) {
- int length = unit_as_string_splitted(str, len_max, value, prec, usys, main_unit);
+ int length = unit_as_string_split_pair(str, len_max, value, prec, usys, main_unit);
/* failed when length is negative, fallback to no split */
if (length >= 0) {
return length;
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 109d615ae83..31fc87d7021 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -106,10 +106,14 @@ World *BKE_world_add(Main *bmain, const char *name)
*/
void BKE_world_copy_data(Main *bmain, World *wrld_dst, const World *wrld_src, const int flag)
{
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
+ /* We always need allocation of our private ID data. */
+ const int flag_private_id_data = flag_subdata & ~LIB_ID_CREATE_NO_ALLOCATE;
+
if (wrld_src->nodetree) {
- /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level
- * (see BKE_libblock_copy_ex()). */
- BKE_id_copy_ex(bmain, (ID *)wrld_src->nodetree, (ID **)&wrld_dst->nodetree, flag);
+ BKE_id_copy_ex(
+ bmain, (ID *)wrld_src->nodetree, (ID **)&wrld_dst->nodetree, flag_private_id_data);
}
BLI_listbase_clear(&wrld_dst->gpumaterial);
diff --git a/source/blender/blenkernel/nla_private.h b/source/blender/blenkernel/nla_private.h
index 1705cd4effc..ed653182a3e 100644
--- a/source/blender/blenkernel/nla_private.h
+++ b/source/blender/blenkernel/nla_private.h
@@ -24,8 +24,6 @@
#ifndef __NLA_PRIVATE_H__
#define __NLA_PRIVATE_H__
-struct Depsgraph;
-
#include "RNA_types.h"
#include "BLI_bitmap.h"
#include "BLI_ghash.h"
diff --git a/source/blender/blenlib/BLI_array.h b/source/blender/blenlib/BLI_array.h
index a61eff7329e..d687838a896 100644
--- a/source/blender/blenlib/BLI_array.h
+++ b/source/blender/blenlib/BLI_array.h
@@ -83,9 +83,9 @@ void _bli_array_grow_func(void **arr_p,
((void *)(_##arr##_static) != \
NULL) && /* don't add _##arr##_len below because it must be zero */ \
(_bli_array_totalsize_static(arr) >= \
- _##arr##_len + (num))) ? /* we have an empty array and a static var big enough */ \
+ (size_t)(_##arr##_len + (num)))) ? /* we have an empty array and a static var big enough */ \
(void)(arr = (void *)_##arr##_static) : /* use existing static array or allocate */ \
- (LIKELY(_bli_array_totalsize(arr) >= _##arr##_len + (num)) ? \
+ (LIKELY(_bli_array_totalsize(arr) >= (size_t)(_##arr##_len + (num))) ? \
(void)0 /* do nothing */ : \
_bli_array_grow_func((void **)&(arr), \
_##arr##_static, \
diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h
index 72a6a1b0150..87e58d90d3f 100644
--- a/source/blender/blenlib/BLI_dynstr.h
+++ b/source/blender/blenlib/BLI_dynstr.h
@@ -35,7 +35,6 @@
#include "BLI_compiler_attrs.h"
struct DynStr;
-struct MemArena;
/** The abstract DynStr type */
typedef struct DynStr DynStr;
diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h
index d8daa81b58d..d78f167a8fd 100644
--- a/source/blender/blenlib/BLI_fileops.h
+++ b/source/blender/blenlib/BLI_fileops.h
@@ -99,8 +99,13 @@ void BLI_filelist_entry_size_to_string(const struct stat *st,
void BLI_filelist_entry_mode_to_string(
const struct stat *st, const bool compact, char r_mode1[], char r_mode2[], char r_mode3[]);
void BLI_filelist_entry_owner_to_string(const struct stat *st, const bool compact, char r_owner[]);
-void BLI_filelist_entry_datetime_to_string(
- const struct stat *st, const int64_t ts, const bool compact, char r_time[], char r_date[]);
+void BLI_filelist_entry_datetime_to_string(const struct stat *st,
+ const int64_t ts,
+ const bool compact,
+ char r_time[],
+ char r_date[],
+ bool *r_is_today,
+ bool *r_is_yesterday);
/* Files */
diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h
index a348694c4da..abfd561200c 100644
--- a/source/blender/blenlib/BLI_kdopbvh.h
+++ b/source/blender/blenlib/BLI_kdopbvh.h
@@ -177,6 +177,12 @@ int BLI_bvhtree_find_nearest(BVHTree *tree,
BVHTree_NearestPointCallback callback,
void *userdata);
+int BLI_bvhtree_find_nearest_first(BVHTree *tree,
+ const float co[3],
+ const float dist_sq,
+ BVHTree_NearestPointCallback callback,
+ void *userdata);
+
int BLI_bvhtree_ray_cast_ex(BVHTree *tree,
const float co[3],
const float dir[3],
diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h
index c235a72e7e4..b8b62dd3451 100644
--- a/source/blender/blenlib/BLI_listbase.h
+++ b/source/blender/blenlib/BLI_listbase.h
@@ -171,12 +171,21 @@ struct LinkData *BLI_genericNodeN(void *data);
#define LISTBASE_FOREACH(type, var, list) \
for (type var = (type)((list)->first); var != NULL; var = (type)(((Link *)(var))->next))
+#define LISTBASE_FOREACH_BACKWARD(type, var, list) \
+ for (type var = (type)((list)->last); var != NULL; var = (type)(((Link *)(var))->prev))
+
/** A version of #LISTBASE_FOREACH that supports removing the item we're looping over. */
#define LISTBASE_FOREACH_MUTABLE(type, var, list) \
for (type var = (type)((list)->first), *var##_iter_next; \
((var != NULL) ? ((void)(var##_iter_next = (type)(((Link *)(var))->next)), 1) : 0); \
var = var##_iter_next)
+/** A version of #LISTBASE_FOREACH_BACKWARD that supports removing the item we're looping over. */
+#define LISTBASE_FOREACH_BACKWARD_MUTABLE(type, var, list) \
+ for (type var = (type)((list)->last), *var##_iter_prev; \
+ ((var != NULL) ? ((void)(var##_iter_prev = (type)(((Link *)(var))->prev)), 1) : 0); \
+ var = var##_iter_prev)
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h
index deb29605552..7b770f2dd3e 100644
--- a/source/blender/blenlib/BLI_math_base.h
+++ b/source/blender/blenlib/BLI_math_base.h
@@ -121,6 +121,9 @@ MINLINE float max_fff(float a, float b, float c);
MINLINE float min_ffff(float a, float b, float c, float d);
MINLINE float max_ffff(float a, float b, float c, float d);
+MINLINE double min_dd(double a, double b);
+MINLINE double max_dd(double a, double b);
+
MINLINE int min_ii(int a, int b);
MINLINE int max_ii(int a, int b);
MINLINE int min_iii(int a, int b, int c);
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index 39b1b96d009..caecc0aebc2 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -188,6 +188,10 @@ float dist_squared_to_projected_aabb_simple(const float projmat[4][4],
const float bbmax[3]);
float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2]);
+double closest_to_line_v2_db(double r_close[2],
+ const double p[2],
+ const double l1[2],
+ const double l2[2]);
float closest_to_line_v3(float r_close[3], const float p[3], const float l1[3], const float l2[3]);
void closest_to_line_segment_v2(float r_close[2],
const float p[2],
@@ -267,7 +271,12 @@ bool isect_seg_seg_v2_simple(const float v1[2],
const float v2[2],
const float v3[2],
const float v4[2]);
-
+int isect_seg_seg_v2_lambda_mu_db(const double v1[2],
+ const double v2[2],
+ const double v3[2],
+ const double v4[2],
+ double *r_lambda,
+ double *r_mu);
int isect_line_sphere_v3(const float l1[3],
const float l2[3],
const float sp[3],
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 52d976daa2d..f5d87667b73 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -41,6 +41,7 @@ void zero_m4(float R[4][4]);
void unit_m2(float R[2][2]);
void unit_m3(float R[3][3]);
void unit_m4(float R[4][4]);
+void unit_m4_db(double m[4][4]);
void copy_m2_m2(float R[2][2], const float A[2][2]);
void copy_m3_m3(float R[3][3], const float A[3][3]);
@@ -48,9 +49,14 @@ void copy_m4_m4(float R[4][4], const float A[4][4]);
void copy_m3_m4(float R[3][3], const float A[4][4]);
void copy_m4_m3(float R[4][4], const float A[3][3]);
+void copy_m4_m4_db(double m1[4][4], const double m2[4][4]);
+
/* double->float */
void copy_m3_m3d(float R[3][3], const double A[3][3]);
+/* float->double */
+void copy_m4d_m4(double R[4][4], const float A[4][4]);
+
void swap_m3m3(float A[3][3], float B[3][3]);
void swap_m4m4(float A[4][4], float B[4][4]);
@@ -82,6 +88,8 @@ void mul_m3_m3m3_uniq(float R[3][3], const float A[3][3], const float B[3][3]);
void mul_m3_m3_pre(float R[3][3], const float A[3][3]);
void mul_m3_m3_post(float R[3][3], const float B[3][3]);
void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4]);
+void mul_m4_m4m4_db_uniq(double R[4][4], const double A[4][4], const double B[4][4]);
+void mul_m4db_m4db_m4fl_uniq(double R[4][4], const double A[4][4], const float B[4][4]);
void mul_m4_m4_pre(float R[4][4], const float A[4][4]);
void mul_m4_m4_post(float R[4][4], const float B[4][4]);
@@ -173,11 +181,14 @@ void _va_mul_m4_series_9(float R[4][4],
void mul_m4_v3(const float M[4][4], float r[3]);
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3]);
+void mul_v3_m4v3_db(double r[3], const double mat[4][4], const double vec[3]);
+void mul_v4_m4v3_db(double r[4], const double mat[4][4], const double vec[3]);
void mul_v2_m4v3(float r[2], const float M[4][4], const float v[3]);
void mul_v2_m2v2(float r[2], const float M[2][2], const float v[2]);
void mul_m2v2(const float M[2][2], float v[2]);
void mul_mat3_m4_v3(const float M[4][4], float r[3]);
void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3]);
+void mul_v3_mat3_m4v3_db(double r[3], const double M[4][4], const double v[3]);
void mul_m4_v4(const float M[4][4], float r[4]);
void mul_v4_m4v4(float r[4], const float M[4][4], const float v[4]);
void mul_v4_m4v3(float r[4], const float M[4][4], const float v[3]); /* v has implicit w = 1.0f */
diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h
index 7a4ac14970f..1e56b80bcf2 100644
--- a/source/blender/blenlib/BLI_math_rotation.h
+++ b/source/blender/blenlib/BLI_math_rotation.h
@@ -96,6 +96,8 @@ void rotation_between_vecs_to_mat3(float m[3][3], const float v1[3], const float
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3]);
void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4]);
+float quat_split_swing_and_twist(const float q[4], int axis, float r_swing[4], float r_twist[4]);
+
float angle_normalized_qt(const float q[4]);
float angle_normalized_qtqt(const float q1[4], const float q2[4]);
float angle_qt(const float q[4]);
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 53e686c87a6..31d725af5ad 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -103,9 +103,11 @@ MINLINE void add_v2_fl(float r[2], float f);
MINLINE void add_v3_fl(float r[3], float f);
MINLINE void add_v4_fl(float r[4], float f);
MINLINE void add_v2_v2(float r[2], const float a[2]);
+MINLINE void add_v2_v2_db(double r[2], const double a[2]);
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2]);
MINLINE void add_v2_v2v2_int(int r[2], const int a[2], const int b[2]);
MINLINE void add_v3_v3(float r[3], const float a[3]);
+MINLINE void add_v3_v3_db(double r[3], const double a[3]);
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3]);
MINLINE void add_v4_v4(float r[4], const float a[4]);
MINLINE void add_v4_v4v4(float r[4], const float a[4], const float b[4]);
@@ -115,10 +117,12 @@ MINLINE void add_v3fl_v3fl_v3s(float r[3], const float a[3], const short b[3]);
MINLINE void sub_v2_v2(float r[2], const float a[2]);
MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2]);
+MINLINE void sub_v2_v2v2_db(double r[2], const double a[2], const double b[2]);
MINLINE void sub_v2_v2v2_int(int r[2], const int a[2], const int b[2]);
MINLINE void sub_v3_v3(float r[3], const float a[3]);
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3]);
MINLINE void sub_v3_v3v3_int(int r[3], const int a[3], const int b[3]);
+MINLINE void sub_v3_v3v3_db(double r[3], const double a[3], const double b[3]);
MINLINE void sub_v4_v4(float r[4], const float a[4]);
MINLINE void sub_v4_v4v4(float r[4], const float a[4], const float b[4]);
@@ -127,6 +131,7 @@ MINLINE void sub_v3db_v3fl_v3fl(double r[3], const float a[3], const float b[3])
MINLINE void mul_v2_fl(float r[2], float f);
MINLINE void mul_v2_v2fl(float r[2], const float a[2], float f);
MINLINE void mul_v3_fl(float r[3], float f);
+MINLINE void mul_v3db_db(double r[3], double f);
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f);
MINLINE void mul_v2_v2(float r[2], const float a[2]);
MINLINE void mul_v2_v2v2(float r[2], const float a[2], const float b[2]);
@@ -181,6 +186,7 @@ MINLINE void abs_v4(float r[4]);
MINLINE void abs_v4_v4(float r[4], const float a[4]);
MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE double dot_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float dot_v3v3v3(const float p[3],
const float a[3],
@@ -189,9 +195,12 @@ MINLINE float dot_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESU
MINLINE double dot_v3db_v3fl(const double a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
+MINLINE double dot_v3v3_db(const double a[3], const double b[3]) ATTR_WARN_UNUSED_RESULT;
+
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 cross_v3_v3v3_db(double r[3], const double a[3], const double b[3]);
MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3]);
@@ -206,8 +215,10 @@ MINLINE int len_manhattan_v2_int(const int v[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_manhattan_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE double len_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_v2v2_int(const int v1[2], const int v2[2]);
MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
+MINLINE double len_squared_v2v2_db(const double a[2], const double b[2]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_squared_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT;
MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/blenlib/BLI_memiter.h b/source/blender/blenlib/BLI_memiter.h
index 6f6316e15e4..9f5be292dd8 100644
--- a/source/blender/blenlib/BLI_memiter.h
+++ b/source/blender/blenlib/BLI_memiter.h
@@ -33,7 +33,6 @@ extern "C" {
#define BLI_MEMITER_DEFAULT_SIZE (1 << 19)
struct BLI_memiter;
-struct BLI_memiter_chunk;
typedef struct BLI_memiter BLI_memiter;
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 99e86615e50..75d5cb286ac 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -29,8 +29,6 @@ extern "C" {
#include "BLI_compiler_attrs.h"
-struct ListBase;
-
void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1);
void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1);
const char *BLI_getenv(const char *env) ATTR_NONNULL(1);
diff --git a/source/blender/blenlib/BLI_polyfill_2d_beautify.h b/source/blender/blenlib/BLI_polyfill_2d_beautify.h
index f815459fdf5..042cb7e0ea9 100644
--- a/source/blender/blenlib/BLI_polyfill_2d_beautify.h
+++ b/source/blender/blenlib/BLI_polyfill_2d_beautify.h
@@ -36,9 +36,10 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2],
const float v2[2],
const float v3[2],
const float v4[2],
- const bool lock_degenerate);
+ const bool lock_degenerate,
+ float *r_area);
#define BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4) \
- BLI_polyfill_beautify_quad_rotate_calc_ex(v1, v2, v3, v4, false)
+ BLI_polyfill_beautify_quad_rotate_calc_ex(v1, v2, v3, v4, false, NULL)
/* avoid realloc's when creating new structures for polyfill ngons */
#define BLI_POLYFILL_ALLOC_NGON_RESERVE 64
diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h
index 70ffb46e952..cab2e68ca2b 100644
--- a/source/blender/blenlib/BLI_string.h
+++ b/source/blender/blenlib/BLI_string.h
@@ -100,7 +100,7 @@ char *BLI_strncasestr(const char *s, const char *find, size_t len) ATTR_WARN_UNU
int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BLI_strncasecmp(const char *s1, const char *s2, size_t len) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
-int BLI_natstrcmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+int BLI_strcasecmp_natural(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
int BLI_strcmp_ignore_pad(const char *str1,
const char *str2,
const char pad) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
diff --git a/source/blender/blenlib/BLI_system.h b/source/blender/blenlib/BLI_system.h
index f4c0399e959..8c0c9ad99bf 100644
--- a/source/blender/blenlib/BLI_system.h
+++ b/source/blender/blenlib/BLI_system.h
@@ -19,11 +19,16 @@
#include <stdio.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/** \file
* \ingroup bli
*/
int BLI_cpu_support_sse2(void);
+int BLI_cpu_support_sse41(void);
void BLI_system_backtrace(FILE *fp);
/* Get CPU brand, result is to be MEM_freeN()-ed. */
@@ -52,4 +57,8 @@ int BLI_system_memory_max_in_megabytes_int(void);
# define BLI_SYSTEM_PID_H <unistd.h>
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* __BLI_SYSTEM_H__ */
diff --git a/source/blender/blenlib/intern/BLI_filelist.c b/source/blender/blenlib/intern/BLI_filelist.c
index 91f16ca9b7b..c92505acb54 100644
--- a/source/blender/blenlib/intern/BLI_filelist.c
+++ b/source/blender/blenlib/intern/BLI_filelist.c
@@ -107,7 +107,7 @@ static int bli_compare(struct direntry *entry1, struct direntry *entry2)
return 1;
}
- return (BLI_natstrcmp(entry1->relname, entry2->relname));
+ return (BLI_strcasecmp_natural(entry1->relname, entry2->relname));
}
struct BuildDirCtx {
@@ -261,36 +261,17 @@ unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **r_
*/
void BLI_filelist_entry_size_to_string(const struct stat *st,
const uint64_t sz,
- const bool compact,
+ /* Used to change MB -> M, etc. - is that really useful? */
+ const bool UNUSED(compact),
char r_size[FILELIST_DIRENTRY_SIZE_LEN])
{
- double size;
- const char *fmt;
- const char *units[] = {"KiB", "MiB", "GiB", "TiB", NULL};
- const char *units_compact[] = {"K", "M", "G", "T", NULL};
- const char *unit = "B";
-
/*
* Seems st_size is signed 32-bit value in *nix and Windows. This
* will buy us some time until files get bigger than 4GB or until
* everyone starts using __USE_FILE_OFFSET64 or equivalent.
*/
- size = (double)(st ? st->st_size : sz);
-
- if (size > 1024.0) {
- const char **u;
- for (u = compact ? units_compact : units, size /= 1024.0; size > 1024.0 && *(u + 1);
- u++, size /= 1024.0) {
- /* pass */
- }
- fmt = size > 100.0 ? "%.0f %s" : (size > 10.0 ? "%.1f %s" : "%.2f %s");
- unit = *u;
- }
- else {
- fmt = "%.0f %s";
- }
-
- BLI_snprintf(r_size, sizeof(*r_size) * FILELIST_DIRENTRY_SIZE_LEN, fmt, size, unit);
+ double size = (double)(st ? st->st_size : sz);
+ BLI_str_format_byte_unit(r_size, size, true);
}
/**
@@ -366,14 +347,45 @@ void BLI_filelist_entry_owner_to_string(const struct stat *st,
/**
* Convert given entry's time into human-readable strings.
+ *
+ * \param r_is_today: optional, returns true if the date matches today's.
+ * \param r_is_yesterday: optional, returns true if the date matches yesterday's.
*/
void BLI_filelist_entry_datetime_to_string(const struct stat *st,
const int64_t ts,
const bool compact,
char r_time[FILELIST_DIRENTRY_TIME_LEN],
- char r_date[FILELIST_DIRENTRY_DATE_LEN])
+ char r_date[FILELIST_DIRENTRY_DATE_LEN],
+ bool *r_is_today,
+ bool *r_is_yesterday)
{
- time_t ts_mtime = ts;
+ int today_year = 0;
+ int today_yday = 0;
+ int yesterday_year = 0;
+ int yesterday_yday = 0;
+
+ if (r_is_today || r_is_yesterday) {
+ /* Localtime() has only one buffer so need to get data out before called again. */
+ const time_t ts_now = time(NULL);
+ struct tm *today = localtime(&ts_now);
+
+ today_year = today->tm_year;
+ today_yday = today->tm_yday;
+ /* Handle a yesterday that spans a year */
+ today->tm_mday--;
+ mktime(today);
+ yesterday_year = today->tm_year;
+ yesterday_yday = today->tm_yday;
+
+ if (r_is_today) {
+ *r_is_today = false;
+ }
+ if (r_is_yesterday) {
+ *r_is_yesterday = false;
+ }
+ }
+
+ const time_t ts_mtime = ts;
const struct tm *tm = localtime(st ? &st->st_mtime : &ts_mtime);
const time_t zero = 0;
@@ -385,12 +397,20 @@ void BLI_filelist_entry_datetime_to_string(const struct stat *st,
if (r_time) {
strftime(r_time, sizeof(*r_time) * FILELIST_DIRENTRY_TIME_LEN, "%H:%M", tm);
}
+
if (r_date) {
strftime(r_date,
sizeof(*r_date) * FILELIST_DIRENTRY_DATE_LEN,
- compact ? "%d/%m/%y" : "%d-%b-%y",
+ compact ? "%d/%m/%y" : "%d %b %Y",
tm);
}
+
+ if (r_is_today && (tm->tm_year == today_year) && (tm->tm_yday == today_yday)) {
+ *r_is_today = true;
+ }
+ else if (r_is_yesterday && (tm->tm_year == yesterday_year) && (tm->tm_yday == yesterday_yday)) {
+ *r_is_yesterday = true;
+ }
}
/**
diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c
index 769bb02e2b9..05ffb02597d 100644
--- a/source/blender/blenlib/intern/BLI_ghash.c
+++ b/source/blender/blenlib/intern/BLI_ghash.c
@@ -886,7 +886,7 @@ bool BLI_ghash_ensure_p_ex(GHash *gh, const void *key, void ***r_key, void ***r_
const bool haskey = (e != NULL);
if (!haskey) {
- /* pass 'key' incase we resize */
+ /* Pass 'key' in case we resize. */
e = BLI_mempool_alloc(gh->entrypool);
ghash_insert_ex_keyonly_entry(gh, (void *)key, bucket_index, (Entry *)e);
e->e.key = NULL; /* caller must re-assign */
@@ -1189,7 +1189,7 @@ bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key)
const bool haskey = (e != NULL);
if (!haskey) {
- /* pass 'key' incase we resize */
+ /* Pass 'key' in case we resize */
e = BLI_mempool_alloc(((GHash *)gs)->entrypool);
ghash_insert_ex_keyonly_entry((GHash *)gs, (void *)key, bucket_index, (Entry *)e);
e->key = NULL; /* caller must re-assign */
diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c
index 0e93fd8e13b..ed3c7096865 100644
--- a/source/blender/blenlib/intern/BLI_kdopbvh.c
+++ b/source/blender/blenlib/intern/BLI_kdopbvh.c
@@ -1467,6 +1467,95 @@ int BLI_bvhtree_find_nearest(BVHTree *tree,
/** \} */
/* -------------------------------------------------------------------- */
+/** \name BLI_bvhtree_find_nearest_first
+ * \{ */
+
+static bool isect_aabb_v3(BVHNode *node, const float co[3])
+{
+ const BVHTreeAxisRange *bv = (const BVHTreeAxisRange *)node->bv;
+
+ if (co[0] > bv[0].min && co[0] < bv[0].max && co[1] > bv[1].min && co[1] < bv[1].max &&
+ co[2] > bv[2].min && co[2] < bv[2].max) {
+ return true;
+ }
+
+ return false;
+}
+
+static bool dfs_find_duplicate_fast_dfs(BVHNearestData *data, BVHNode *node)
+{
+ if (node->totnode == 0) {
+ if (isect_aabb_v3(node, data->co)) {
+ if (data->callback) {
+ const float dist_sq = data->nearest.dist_sq;
+ data->callback(data->userdata, node->index, data->co, &data->nearest);
+ return (data->nearest.dist_sq < dist_sq);
+ }
+ else {
+ data->nearest.index = node->index;
+ return true;
+ }
+ }
+ }
+ else {
+ /* Better heuristic to pick the closest node to dive on */
+ int i;
+
+ if (data->proj[node->main_axis] <= node->children[0]->bv[node->main_axis * 2 + 1]) {
+ for (i = 0; i != node->totnode; i++) {
+ if (isect_aabb_v3(node->children[i], data->co)) {
+ if (dfs_find_duplicate_fast_dfs(data, node->children[i])) {
+ return true;
+ }
+ }
+ }
+ }
+ else {
+ for (i = node->totnode; i--;) {
+ if (isect_aabb_v3(node->children[i], data->co)) {
+ if (dfs_find_duplicate_fast_dfs(data, node->children[i])) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+/**
+ * Find the first node nearby.
+ * Favors speed over quality since it doesn't find the best target node.
+ */
+int BLI_bvhtree_find_nearest_first(BVHTree *tree,
+ const float co[3],
+ const float dist_sq,
+ BVHTree_NearestPointCallback callback,
+ void *userdata)
+{
+ BVHNearestData data;
+ BVHNode *root = tree->nodes[tree->totleaf];
+
+ /* init data to search */
+ data.tree = tree;
+ data.co = co;
+
+ data.callback = callback;
+ data.userdata = userdata;
+ data.nearest.index = -1;
+ data.nearest.dist_sq = dist_sq;
+
+ /* dfs search */
+ if (root) {
+ dfs_find_duplicate_fast_dfs(&data, root);
+ }
+
+ return data.nearest.index;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name BLI_bvhtree_ray_cast
*
* raycast is done by performing a DFS on the BVHTree and saving the closest hit.
diff --git a/source/blender/blenlib/intern/boxpack_2d.c b/source/blender/blenlib/intern/boxpack_2d.c
index 196d45967be..ddc7f9ee4c7 100644
--- a/source/blender/blenlib/intern/boxpack_2d.c
+++ b/source/blender/blenlib/intern/boxpack_2d.c
@@ -273,12 +273,12 @@ static int vertex_sort(const void *p1, const void *p2, void *vs_ctx_p)
/** \} */
/**
- * Main boxpacking function accessed from other functions
+ * Main box-packing function accessed from other functions
* This sets boxes x,y to positive values, sorting from 0,0 outwards.
* There is no limit to the space boxes may take, only that they will be packed
* tightly into the lower left hand corner (0,0)
*
- * \param boxarray: a pre allocated array of boxes.
+ * \param boxarray: a pre-allocated array of boxes.
* only the 'box->x' and 'box->y' are set, 'box->w' and 'box->h' are used,
* 'box->index' is not used at all, the only reason its there
* is that the box array is sorted by area and programs need to be able
diff --git a/source/blender/blenlib/intern/delaunay_2d.c b/source/blender/blenlib/intern/delaunay_2d.c
index 23f560c5463..102ea8eb234 100644
--- a/source/blender/blenlib/intern/delaunay_2d.c
+++ b/source/blender/blenlib/intern/delaunay_2d.c
@@ -115,99 +115,6 @@ static void validate_face_centroid(SymEdge *se);
static void validate_cdt(CDT_state *cdt, bool check_all_tris);
#endif
-/* TODO: move these to BLI_vector... and BLI_math... */
-static double max_dd(const double a, const double b)
-{
- return (a > b) ? a : b;
-}
-
-static double len_v2v2_db(const double a[2], const double b[2])
-{
- return sqrt((b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]));
-}
-
-static double len_squared_v2v2_db(const double a[2], const double b[2])
-{
- return (b[0] - a[0]) * (b[0] - a[0]) + (b[1] - a[1]) * (b[1] - a[1]);
-}
-
-static void add_v2_v2_db(double a[2], const double b[2])
-{
- a[0] += b[0];
- a[1] += b[1];
-}
-
-static void sub_v2_v2v2_db(double *a, const double *b, const double *c)
-{
- a[0] = b[0] - c[0];
- a[1] = b[1] - c[1];
-}
-
-static double dot_v2v2_db(const double *a, const double *b)
-{
- return a[0] * b[0] + a[1] * b[1];
-}
-
-static double closest_to_line_v2_db(double r_close[2],
- const double p[2],
- const double l1[2],
- const double l2[2])
-{
- double h[2], u[2], lambda, denom;
- sub_v2_v2v2_db(u, l2, l1);
- sub_v2_v2v2_db(h, p, l1);
- denom = dot_v2v2_db(u, u);
- if (denom < DBL_EPSILON) {
- r_close[0] = l1[0];
- r_close[1] = l1[1];
- return 0.0;
- }
- lambda = dot_v2v2_db(u, h) / dot_v2v2_db(u, u);
- r_close[0] = l1[0] + u[0] * lambda;
- r_close[1] = l1[1] + u[1] * lambda;
- return lambda;
-}
-
-/**
- * If intersection == ISECT_LINE_LINE_CROSS or ISECT_LINE_LINE_NONE:
- * <pre>
- * pt = v1 + lamba * (v2 - v1) = v3 + mu * (v4 - v3)
- * </pre>
- */
-static int isect_seg_seg_v2_lambda_mu_db(const double v1[2],
- const double v2[2],
- const double v3[2],
- const double v4[2],
- double *r_lambda,
- double *r_mu)
-{
- double div, lambda, mu;
-
- div = (v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0]);
- if (fabs(div) < DBL_EPSILON) {
- return ISECT_LINE_LINE_COLINEAR;
- }
-
- lambda = ((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div;
-
- mu = ((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div;
-
- if (r_lambda) {
- *r_lambda = lambda;
- }
- if (r_mu) {
- *r_mu = mu;
- }
-
- if (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0) {
- if (lambda == 0.0 || lambda == 1.0 || mu == 0.0 || mu == 1.0) {
- return ISECT_LINE_LINE_EXACT;
- }
- return ISECT_LINE_LINE_CROSS;
- }
- return ISECT_LINE_LINE_NONE;
-}
-
/** return 1 if a,b,c forms CCW angle, -1 if a CW angle, 0 if straight */
static int CCW_test(const double a[2], const double b[2], const double c[2])
{
diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c
index 7be7674069c..b5a950d6851 100644
--- a/source/blender/blenlib/intern/freetypefont.c
+++ b/source/blender/blenlib/intern/freetypefont.c
@@ -565,7 +565,7 @@ VChar *BLI_vfontchar_copy(const VChar *vchar_src, const int UNUSED(flag))
* between them
* </pre>
*
- * Each glyph's original outline points are located on a grid of indivisible units.
+ * Each glyphs original outline points are located on a grid of indivisible units.
* The points are stored in the font file as 16-bit integer grid coordinates,
* with the grid origin's being at (0, 0); they thus range from -16384 to 16383.
*
diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c
index 320f8a0f1ab..47327a878d4 100644
--- a/source/blender/blenlib/intern/math_base_inline.c
+++ b/source/blender/blenlib/intern/math_base_inline.c
@@ -353,6 +353,15 @@ MINLINE float max_ff(float a, float b)
return (a > b) ? a : b;
}
+MINLINE double min_dd(double a, double b)
+{
+ return (a < b) ? a : b;
+}
+MINLINE double max_dd(double a, double b)
+{
+ return (a > b) ? a : b;
+}
+
MINLINE int min_ii(int a, int b)
{
return (a < b) ? a : b;
diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c
index f07c2ec159e..cc29ebe4f20 100644
--- a/source/blender/blenlib/intern/math_color.c
+++ b/source/blender/blenlib/intern/math_color.c
@@ -153,7 +153,7 @@ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, in
cr = (0.5f * sr) - (0.41869f * sg) - (0.08131f * sb) + 128.0f;
break;
default:
- assert(!"invalid colorspace");
+ BLI_assert(!"invalid colorspace");
break;
}
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index 06fd5c70772..f1575ed2b2d 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -1356,6 +1356,52 @@ bool isect_seg_seg_v2_simple(const float v1[2],
}
/**
+ * If intersection == ISECT_LINE_LINE_CROSS or ISECT_LINE_LINE_NONE:
+ * <pre>
+ * pt = v1 + lambda * (v2 - v1) = v3 + mu * (v4 - v3)
+ * </pre>
+ * \returns intersection type:
+ * - ISECT_LINE_LINE_COLINEAR: collinear.
+ * - ISECT_LINE_LINE_EXACT: intersection at an endpoint of either.
+ * - ISECT_LINE_LINE_CROSS: interaction, not at an endpoint.
+ * - ISECT_LINE_LINE_NONE: no intersection.
+ * Also returns lambda and mu in r_lambda and r_mu.
+ */
+int isect_seg_seg_v2_lambda_mu_db(const double v1[2],
+ const double v2[2],
+ const double v3[2],
+ const double v4[2],
+ double *r_lambda,
+ double *r_mu)
+{
+ double div, lambda, mu;
+
+ div = (v2[0] - v1[0]) * (v4[1] - v3[1]) - (v2[1] - v1[1]) * (v4[0] - v3[0]);
+ if (fabs(div) < DBL_EPSILON) {
+ return ISECT_LINE_LINE_COLINEAR;
+ }
+
+ lambda = ((v1[1] - v3[1]) * (v4[0] - v3[0]) - (v1[0] - v3[0]) * (v4[1] - v3[1])) / div;
+
+ mu = ((v1[1] - v3[1]) * (v2[0] - v1[0]) - (v1[0] - v3[0]) * (v2[1] - v1[1])) / div;
+
+ if (r_lambda) {
+ *r_lambda = lambda;
+ }
+ if (r_mu) {
+ *r_mu = mu;
+ }
+
+ if (lambda >= 0.0 && lambda <= 1.0 && mu >= 0.0 && mu <= 1.0) {
+ if (lambda == 0.0 || lambda == 1.0 || mu == 0.0 || mu == 1.0) {
+ return ISECT_LINE_LINE_EXACT;
+ }
+ return ISECT_LINE_LINE_CROSS;
+ }
+ return ISECT_LINE_LINE_NONE;
+}
+
+/**
* \param l1, l2: Coordinates (point of line).
* \param sp, r: Coordinate and radius (sphere).
* \return r_p1, r_p2: Intersection coordinates.
@@ -3187,6 +3233,26 @@ float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2],
return lambda;
}
+double closest_to_line_v2_db(double r_close[2],
+ const double p[2],
+ const double l1[2],
+ const double l2[2])
+{
+ double h[2], u[2], lambda, denom;
+ sub_v2_v2v2_db(u, l2, l1);
+ sub_v2_v2v2_db(h, p, l1);
+ denom = dot_v2v2_db(u, u);
+ if (denom < DBL_EPSILON) {
+ r_close[0] = l1[0];
+ r_close[1] = l1[1];
+ return 0.0;
+ }
+ lambda = dot_v2v2_db(u, h) / dot_v2v2_db(u, u);
+ r_close[0] = l1[0] + u[0] * lambda;
+ r_close[1] = l1[1] + u[1] * lambda;
+ return lambda;
+}
+
float ray_point_factor_v3_ex(const float p[3],
const float ray_origin[3],
const float ray_direction[3],
@@ -3452,7 +3518,7 @@ bool clip_segment_v3_plane(
}
}
- /* incase input/output values match (above also) */
+ /* In case input/output values match (above also). */
const float p1_copy[3] = {UNPACK3(p1)};
copy_v3_v3(r_p2, p2);
copy_v3_v3(r_p1, p1_copy);
@@ -3511,7 +3577,7 @@ bool clip_segment_v3_plane_n(const float p1[3],
}
}
- /* incase input/output values match */
+ /* In case input/output values match. */
const float p1_copy[3] = {UNPACK3(p1)};
madd_v3_v3v3fl(r_p1, p1_copy, dp, p1_fac);
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 7c64206134b..2568d42566c 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -71,6 +71,15 @@ void unit_m4(float m[4][4])
m[3][0] = m[3][1] = m[3][2] = 0.0f;
}
+void unit_m4_db(double m[4][4])
+{
+ m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;
+ m[0][1] = m[0][2] = m[0][3] = 0.0f;
+ m[1][0] = m[1][2] = m[1][3] = 0.0f;
+ m[2][0] = m[2][1] = m[2][3] = 0.0f;
+ m[3][0] = m[3][1] = m[3][2] = 0.0f;
+}
+
void copy_m2_m2(float m1[2][2], const float m2[2][2])
{
memcpy(m1, m2, sizeof(float[2][2]));
@@ -87,6 +96,11 @@ void copy_m4_m4(float m1[4][4], const float m2[4][4])
memcpy(m1, m2, sizeof(float[4][4]));
}
+void copy_m4_m4_db(double m1[4][4], const double m2[4][4])
+{
+ memcpy(m1, m2, sizeof(double[4][4]));
+}
+
void copy_m3_m4(float m1[3][3], const float m2[4][4])
{
m1[0][0] = m2[0][0];
@@ -127,6 +141,29 @@ void copy_m4_m3(float m1[4][4], const float m2[3][3]) /* no clear */
m1[3][3] = 1.0f;
}
+void copy_m4d_m4(double m1[4][4], const float m2[4][4])
+{
+ m1[0][0] = m2[0][0];
+ m1[0][1] = m2[0][1];
+ m1[0][2] = m2[0][2];
+ m1[0][3] = m2[0][3];
+
+ m1[1][0] = m2[1][0];
+ m1[1][1] = m2[1][1];
+ m1[1][2] = m2[1][2];
+ m1[1][3] = m2[1][3];
+
+ m1[2][0] = m2[2][0];
+ m1[2][1] = m2[2][1];
+ m1[2][2] = m2[2][2];
+ m1[2][3] = m2[2][3];
+
+ m1[3][0] = m2[3][0];
+ m1[3][1] = m2[3][1];
+ m1[3][2] = m2[3][2];
+ m1[3][3] = m2[3][3];
+}
+
void copy_m3_m3d(float R[3][3], const double A[3][3])
{
/* Keep it stupid simple for better data flow in CPU. */
@@ -231,6 +268,61 @@ void mul_m4_m4m4_uniq(float R[4][4], const float A[4][4], const float B[4][4])
#endif
}
+void mul_m4_m4m4_db_uniq(double R[4][4], const double A[4][4], const double B[4][4])
+{
+ BLI_assert(R != A && R != B);
+
+ /* matrix product: R[j][k] = A[j][i] . B[i][k] */
+
+ R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0];
+ R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1];
+ R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2] + B[0][3] * A[3][2];
+ R[0][3] = B[0][0] * A[0][3] + B[0][1] * A[1][3] + B[0][2] * A[2][3] + B[0][3] * A[3][3];
+
+ R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0] + B[1][3] * A[3][0];
+ R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1] + B[1][3] * A[3][1];
+ R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2] + B[1][3] * A[3][2];
+ R[1][3] = B[1][0] * A[0][3] + B[1][1] * A[1][3] + B[1][2] * A[2][3] + B[1][3] * A[3][3];
+
+ R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0] + B[2][3] * A[3][0];
+ R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1] + B[2][3] * A[3][1];
+ R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2] + B[2][3] * A[3][2];
+ R[2][3] = B[2][0] * A[0][3] + B[2][1] * A[1][3] + B[2][2] * A[2][3] + B[2][3] * A[3][3];
+
+ R[3][0] = B[3][0] * A[0][0] + B[3][1] * A[1][0] + B[3][2] * A[2][0] + B[3][3] * A[3][0];
+ R[3][1] = B[3][0] * A[0][1] + B[3][1] * A[1][1] + B[3][2] * A[2][1] + B[3][3] * A[3][1];
+ R[3][2] = B[3][0] * A[0][2] + B[3][1] * A[1][2] + B[3][2] * A[2][2] + B[3][3] * A[3][2];
+ R[3][3] = B[3][0] * A[0][3] + B[3][1] * A[1][3] + B[3][2] * A[2][3] + B[3][3] * A[3][3];
+}
+
+void mul_m4db_m4db_m4fl_uniq(double R[4][4], const double A[4][4], const float B[4][4])
+{
+ /* Remove second check since types don't match. */
+ BLI_assert(R != A /* && R != B */);
+
+ /* matrix product: R[j][k] = A[j][i] . B[i][k] */
+
+ R[0][0] = B[0][0] * A[0][0] + B[0][1] * A[1][0] + B[0][2] * A[2][0] + B[0][3] * A[3][0];
+ R[0][1] = B[0][0] * A[0][1] + B[0][1] * A[1][1] + B[0][2] * A[2][1] + B[0][3] * A[3][1];
+ R[0][2] = B[0][0] * A[0][2] + B[0][1] * A[1][2] + B[0][2] * A[2][2] + B[0][3] * A[3][2];
+ R[0][3] = B[0][0] * A[0][3] + B[0][1] * A[1][3] + B[0][2] * A[2][3] + B[0][3] * A[3][3];
+
+ R[1][0] = B[1][0] * A[0][0] + B[1][1] * A[1][0] + B[1][2] * A[2][0] + B[1][3] * A[3][0];
+ R[1][1] = B[1][0] * A[0][1] + B[1][1] * A[1][1] + B[1][2] * A[2][1] + B[1][3] * A[3][1];
+ R[1][2] = B[1][0] * A[0][2] + B[1][1] * A[1][2] + B[1][2] * A[2][2] + B[1][3] * A[3][2];
+ R[1][3] = B[1][0] * A[0][3] + B[1][1] * A[1][3] + B[1][2] * A[2][3] + B[1][3] * A[3][3];
+
+ R[2][0] = B[2][0] * A[0][0] + B[2][1] * A[1][0] + B[2][2] * A[2][0] + B[2][3] * A[3][0];
+ R[2][1] = B[2][0] * A[0][1] + B[2][1] * A[1][1] + B[2][2] * A[2][1] + B[2][3] * A[3][1];
+ R[2][2] = B[2][0] * A[0][2] + B[2][1] * A[1][2] + B[2][2] * A[2][2] + B[2][3] * A[3][2];
+ R[2][3] = B[2][0] * A[0][3] + B[2][1] * A[1][3] + B[2][2] * A[2][3] + B[2][3] * A[3][3];
+
+ R[3][0] = B[3][0] * A[0][0] + B[3][1] * A[1][0] + B[3][2] * A[2][0] + B[3][3] * A[3][0];
+ R[3][1] = B[3][0] * A[0][1] + B[3][1] * A[1][1] + B[3][2] * A[2][1] + B[3][3] * A[3][1];
+ R[3][2] = B[3][0] * A[0][2] + B[3][1] * A[1][2] + B[3][2] * A[2][2] + B[3][3] * A[3][2];
+ R[3][3] = B[3][0] * A[0][3] + B[3][1] * A[1][3] + B[3][2] * A[2][3] + B[3][3] * A[3][3];
+}
+
void mul_m4_m4_pre(float R[4][4], const float A[4][4])
{
BLI_assert(A != R);
@@ -604,6 +696,26 @@ void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
}
+void mul_v3_m4v3_db(double r[3], const double mat[4][4], const double vec[3])
+{
+ const double x = vec[0];
+ const double y = vec[1];
+
+ r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
+ r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
+ r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
+}
+void mul_v4_m4v3_db(double r[4], const double mat[4][4], const double vec[3])
+{
+ const double x = vec[0];
+ const double y = vec[1];
+
+ r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0];
+ r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1];
+ r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2];
+ r[3] = x * mat[0][3] + y * mat[1][3] + mat[2][3] * vec[2] + mat[3][3];
+}
+
void mul_v2_m4v3(float r[2], const float mat[4][4], const float vec[3])
{
const float x = vec[0];
@@ -646,6 +758,16 @@ void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
}
+void mul_v3_mat3_m4v3_db(double r[3], const double mat[4][4], const double vec[3])
+{
+ const double x = vec[0];
+ const double y = vec[1];
+
+ r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2];
+ r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2];
+ r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2];
+}
+
void mul_project_m4_v3(const float mat[4][4], float vec[3])
{
/* absolute value to not flip the frustum upside down behind the camera */
@@ -1891,7 +2013,7 @@ void rotate_m4(float mat[4][4], const char axis, const float angle)
const float angle_cos = cosf(angle);
const float angle_sin = sinf(angle);
- assert(axis >= 'X' && axis <= 'Z');
+ BLI_assert(axis >= 'X' && axis <= 'Z');
switch (axis) {
case 'X':
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 47814b1080c..5762d164914 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -535,6 +535,49 @@ void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q
mul_qt_qtqt(q, tquat, q2);
}
+/** Decompose a quaternion into a swing rotation (quaternion with the selected
+ * axis component locked at zero), followed by a twist rotation around the axis.
+ *
+ * \param q: input quaternion.
+ * \param axis: twist axis in [0,1,2]
+ * \param r_swing[out]: if not NULL, receives the swing quaternion.
+ * \param r_twist[out]: if not NULL, receives the twist quaternion.
+ * \returns twist angle.
+ */
+float quat_split_swing_and_twist(const float q[4], int axis, float r_swing[4], float r_twist[4])
+{
+ BLI_assert(axis >= 0 && axis <= 2);
+
+ /* Half-twist angle can be computed directly. */
+ float t = atan2f(q[axis + 1], q[0]);
+
+ if (r_swing || r_twist) {
+ float sin_t = sinf(t), cos_t = cosf(t);
+
+ /* Compute swing by multiplying the original quaternion by inverted twist. */
+ if (r_swing) {
+ float twist_inv[4];
+
+ twist_inv[0] = cos_t;
+ zero_v3(twist_inv + 1);
+ twist_inv[axis + 1] = -sin_t;
+
+ mul_qt_qtqt(r_swing, q, twist_inv);
+
+ BLI_assert(fabsf(r_swing[axis + 1]) < BLI_ASSERT_UNIT_EPSILON);
+ }
+
+ /* Output twist last just in case q ovelaps r_twist. */
+ if (r_twist) {
+ r_twist[0] = cos_t;
+ zero_v3(r_twist + 1);
+ r_twist[axis + 1] = sin_t;
+ }
+ }
+
+ return 2.0f * t;
+}
+
/* -------------------------------------------------------------------- */
/** \name Quaternion Angle
*
@@ -644,8 +687,8 @@ void vec_to_quat(float q[4], const float vec[3], short axis, const short upflag)
float nor[3], tvec[3];
float angle, si, co, len;
- assert(axis >= 0 && axis <= 5);
- assert(upflag >= 0 && upflag <= 2);
+ BLI_assert(axis >= 0 && axis <= 5);
+ BLI_assert(upflag >= 0 && upflag <= 2);
/* first set the quat to unit */
unit_qt(q);
@@ -1194,7 +1237,7 @@ void axis_angle_to_quat_single(float q[4], const char axis, const float angle)
const float angle_sin = sinf(angle_half);
const int axis_index = (axis - 'X');
- assert(axis >= 'X' && axis <= 'Z');
+ BLI_assert(axis >= 'X' && axis <= 'Z');
q[0] = angle_cos;
zero_v3(q + 1);
@@ -1398,7 +1441,7 @@ void rotate_eul(float beul[3], const char axis, const float ang)
{
float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
- assert(axis >= 'X' && axis <= 'Z');
+ BLI_assert(axis >= 'X' && axis <= 'Z');
eul[0] = eul[1] = eul[2] = 0.0f;
if (axis == 'X') {
@@ -1544,7 +1587,7 @@ static const RotOrderInfo rotOrders[] = {
*/
static const RotOrderInfo *get_rotation_order_info(const short order)
{
- assert(order >= 0 && order <= 6);
+ BLI_assert(order >= 0 && order <= 6);
if (order < 1) {
return &rotOrders[0];
}
@@ -1813,7 +1856,7 @@ void rotate_eulO(float beul[3], const short order, char axis, float ang)
{
float eul[3], mat1[3][3], mat2[3][3], totmat[3][3];
- assert(axis >= 'X' && axis <= 'Z');
+ BLI_assert(axis >= 'X' && axis <= 'Z');
zero_v3(eul);
@@ -2119,8 +2162,8 @@ void quat_apply_track(float quat[4], short axis, short upflag)
{0.0, sqrt_1_2, sqrt_1_2, 0.0},
};
- assert(axis >= 0 && axis <= 5);
- assert(upflag >= 0 && upflag <= 2);
+ BLI_assert(axis >= 0 && axis <= 5);
+ BLI_assert(upflag >= 0 && upflag <= 2);
mul_qt_qtqt(quat, quat, quat_track[axis]);
@@ -2142,7 +2185,7 @@ void vec_apply_track(float vec[3], short axis)
{
float tvec[3];
- assert(axis >= 0 && axis <= 5);
+ BLI_assert(axis >= 0 && axis <= 5);
copy_v3_v3(tvec, vec);
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 865c2f5dc25..b4b53a1dd58 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -355,6 +355,12 @@ MINLINE void add_v2_v2(float r[2], const float a[2])
r[1] += a[1];
}
+MINLINE void add_v2_v2_db(double r[2], const double a[2])
+{
+ r[0] += a[0];
+ r[1] += a[1];
+}
+
MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2])
{
r[0] = a[0] + b[0];
@@ -374,6 +380,13 @@ MINLINE void add_v3_v3(float r[3], const float a[3])
r[2] += a[2];
}
+MINLINE void add_v3_v3_db(double r[3], const double a[3])
+{
+ r[0] += a[0];
+ r[1] += a[1];
+ r[2] += a[2];
+}
+
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
{
r[0] = a[0] + b[0];
@@ -423,6 +436,12 @@ MINLINE void sub_v2_v2v2(float r[2], const float a[2], const float b[2])
r[1] = a[1] - b[1];
}
+MINLINE void sub_v2_v2v2_db(double r[2], const double a[2], const double b[2])
+{
+ r[0] = a[0] - b[0];
+ r[1] = a[1] - b[1];
+}
+
MINLINE void sub_v2_v2v2_int(int r[2], const int a[2], const int b[2])
{
r[0] = a[0] - b[0];
@@ -450,6 +469,13 @@ MINLINE void sub_v3_v3v3_int(int r[3], const int a[3], const int b[3])
r[2] = a[2] - b[2];
}
+MINLINE void sub_v3_v3v3_db(double r[3], const double a[3], const double b[3])
+{
+ r[0] = a[0] - b[0];
+ r[1] = a[1] - b[1];
+ r[2] = a[2] - b[2];
+}
+
MINLINE void sub_v3db_v3fl_v3fl(double r[3], const float a[3], const float b[3])
{
r[0] = (double)a[0] - (double)b[0];
@@ -492,6 +518,13 @@ MINLINE void mul_v3_fl(float r[3], float f)
r[2] *= f;
}
+MINLINE void mul_v3db_db(double r[3], double f)
+{
+ r[0] *= f;
+ r[1] *= f;
+ r[2] *= f;
+}
+
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
{
r[0] = a[0] * f;
@@ -809,6 +842,11 @@ MINLINE float dot_v2v2(const float a[2], const float b[2])
return a[0] * b[0] + a[1] * b[1];
}
+MINLINE double dot_v2v2_db(const double a[2], const double b[2])
+{
+ return a[0] * b[0] + a[1] * b[1];
+}
+
MINLINE float dot_v3v3(const float a[3], const float b[3])
{
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
@@ -836,6 +874,11 @@ MINLINE double dot_v3db_v3fl(const double a[3], const float b[3])
return a[0] * (double)b[0] + a[1] * (double)b[1] + a[2] * (double)b[2];
}
+MINLINE double dot_v3v3_db(const double a[3], const double b[3])
+{
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+
MINLINE float cross_v2v2(const float a[2], const float b[2])
{
return a[0] * b[1] - a[1] * b[0];
@@ -859,6 +902,14 @@ MINLINE void cross_v3_v3v3_hi_prec(float r[3], const float a[3], const float b[3
r[2] = (float)((double)a[0] * (double)b[1] - (double)a[1] * (double)b[0]);
}
+MINLINE void cross_v3_v3v3_db(double r[3], const double a[3], const double b[3])
+{
+ BLI_assert(r != a && r != b);
+ r[0] = a[1] * b[2] - a[2] * b[1];
+ r[1] = a[2] * b[0] - a[0] * b[2];
+ r[2] = a[0] * b[1] - a[1] * b[0];
+}
+
/* Newell's Method */
/* excuse this fairly specific function,
* its used for polygon normals all over the place
@@ -922,6 +973,15 @@ MINLINE float len_v2v2(const float v1[2], const float v2[2])
return sqrtf(x * x + y * y);
}
+MINLINE double len_v2v2_db(const double v1[2], const double v2[2])
+{
+ double x, y;
+
+ x = v1[0] - v2[0];
+ y = v1[1] - v2[1];
+ return sqrt(x * x + y * y);
+}
+
MINLINE float len_v2v2_int(const int v1[2], const int v2[2])
{
float x, y;
@@ -944,6 +1004,14 @@ MINLINE float len_squared_v2v2(const float a[2], const float b[2])
return dot_v2v2(d, d);
}
+MINLINE double len_squared_v2v2_db(const double a[2], const double b[2])
+{
+ double d[2];
+
+ sub_v2_v2v2_db(d, b, a);
+ return dot_v2v2_db(d, d);
+}
+
MINLINE float len_squared_v3v3(const float a[3], const float b[3])
{
float d[3];
diff --git a/source/blender/blenlib/intern/polyfill_2d_beautify.c b/source/blender/blenlib/intern/polyfill_2d_beautify.c
index 3e94ae8de1f..ab397b86b1a 100644
--- a/source/blender/blenlib/intern/polyfill_2d_beautify.c
+++ b/source/blender/blenlib/intern/polyfill_2d_beautify.c
@@ -75,7 +75,7 @@ static int oedge_cmp(const void *a1, const void *a2)
return -1;
}
- /* only for pradictability */
+ /* Only for predictability. */
if (x1->e_half > x2->e_half) {
return 1;
}
@@ -100,6 +100,10 @@ BLI_INLINE bool is_boundary_edge(uint i_a, uint i_b, const uint coord_last)
* - When true, an existing zero area face on either side of the (2 - 4
* split will return a positive value.
* - When false, the check must be non-biased towards either split direction.
+ * \param r_area: Return the area of the quad,
+ * This can be useful when comparing the return value with near zero epsilons.
+ * In this case the epsilon can be scaled by the area to avoid the return value
+ * of very large faces not having a reliable way to detect near-zero output.
*
* \return (negative number means the edge can be rotated, lager == better).
*/
@@ -107,7 +111,8 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2],
const float v2[2],
const float v3[2],
const float v4[2],
- const bool lock_degenerate)
+ const bool lock_degenerate,
+ float *r_area)
{
/* not a loop (only to be able to break out) */
do {
@@ -121,6 +126,13 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2],
BLI_assert((ELEM(v1, v2, v3, v4) == false) && (ELEM(v2, v1, v3, v4) == false) &&
(ELEM(v3, v1, v2, v4) == false) && (ELEM(v4, v1, v2, v3) == false));
+
+ if (r_area) {
+ *r_area = fabsf(area_2x_234) + fabsf(area_2x_241) +
+ /* Include both pairs for predictable results. */
+ fabsf(area_2x_123) + fabsf(area_2x_134) / 8.0f;
+ }
+
/*
* Test for unusable (1-3) state.
* - Area sign flipping to check faces aren't going to point in opposite directions.
@@ -191,7 +203,8 @@ float BLI_polyfill_beautify_quad_rotate_calc_ex(const float v1[2],
static float polyedge_rotate_beauty_calc(const float (*coords)[2],
const struct HalfEdge *edges,
- const struct HalfEdge *e_a)
+ const struct HalfEdge *e_a,
+ float *r_area)
{
const struct HalfEdge *e_b = &edges[e_a->e_radial];
@@ -205,7 +218,7 @@ static float polyedge_rotate_beauty_calc(const float (*coords)[2],
v3 = coords[e_b_other->v];
v4 = coords[e_b->v];
- return BLI_polyfill_beautify_quad_rotate_calc(v1, v2, v3, v4);
+ return BLI_polyfill_beautify_quad_rotate_calc_ex(v1, v2, v3, v4, false, r_area);
}
static void polyedge_beauty_cost_update_single(const float (*coords)[2],
@@ -216,13 +229,18 @@ static void polyedge_beauty_cost_update_single(const float (*coords)[2],
{
const uint i = e->base_index;
/* recalculate edge */
- const float cost = polyedge_rotate_beauty_calc(coords, edges, e);
+ float area;
+ const float cost = polyedge_rotate_beauty_calc(coords, edges, e, &area);
/* We can get cases where both choices generate very small negative costs,
* which leads to infinite loop. Anyway, costs above that are not worth recomputing,
* maybe we could even optimize it to a smaller limit?
* Actually, FLT_EPSILON is too small in some cases, 1e-6f seems to work OK hopefully?
- * See T43578, T49478. */
- if (cost < -1e-6f) {
+ * See T43578, T49478.
+ *
+ * In fact a larger epsilon can still fail when the area of the face is very large,
+ * now the epsilon is scaled by the face area.
+ * See T56532. */
+ if (cost < -1e-6f * max_ff(area, 1.0f)) {
BLI_heap_insert_or_update(eheap, &eheap_table[i], cost, e);
}
else {
@@ -381,7 +399,7 @@ void BLI_polyfill_beautify(const float (*coords)[2],
for (uint i = 0; i < half_edges_len; i++, e++) {
/* Accounts for boundary edged too (UINT_MAX). */
if (e->e_radial < i) {
- const float cost = polyedge_rotate_beauty_calc(coords, half_edges, e);
+ const float cost = polyedge_rotate_beauty_calc(coords, half_edges, e, NULL);
if (cost < 0.0f) {
eheap_table[e->base_index] = BLI_heap_insert(eheap, cost, e);
}
diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c
index 3b69e257f45..4059e0401c0 100644
--- a/source/blender/blenlib/intern/string.c
+++ b/source/blender/blenlib/intern/string.c
@@ -663,8 +663,11 @@ static int left_number_strcmp(const char *s1, const char *s2, int *tiebreaker)
return 0;
}
-/* natural string compare, keeping numbers in order */
-int BLI_natstrcmp(const char *s1, const char *s2)
+/**
+ * Case insensitive, *natural* string comparison,
+ * keeping numbers in order.
+ */
+int BLI_strcasecmp_natural(const char *s1, const char *s2)
{
register int d1 = 0, d2 = 0;
register char c1, c2;
@@ -675,10 +678,7 @@ int BLI_natstrcmp(const char *s1, const char *s2)
* numeric, else do a tolower and char compare */
while (1) {
- c1 = tolower(s1[d1]);
- c2 = tolower(s2[d2]);
-
- if (isdigit(c1) && isdigit(c2)) {
+ if (isdigit(s1[d1]) && isdigit(s2[d2])) {
int numcompare = left_number_strcmp(s1 + d1, s2 + d2, &tiebreaker);
if (numcompare != 0) {
@@ -693,11 +693,11 @@ int BLI_natstrcmp(const char *s1, const char *s2)
while (isdigit(s2[d2])) {
d2++;
}
-
- c1 = tolower(s1[d1]);
- c2 = tolower(s2[d2]);
}
+ c1 = tolower(s1[d1]);
+ c2 = tolower(s2[d2]);
+
/* first check for '.' so "foo.bar" comes before "foo 1.bar" */
if (c1 == '.' && c2 != '.') {
return -1;
diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c
index 88f2e2625e8..941c2b608e6 100644
--- a/source/blender/blenlib/intern/system.c
+++ b/source/blender/blenlib/intern/system.c
@@ -179,6 +179,19 @@ char *BLI_cpu_brand_string(void)
return NULL;
}
+int BLI_cpu_support_sse41(void)
+{
+ int result[4], num;
+ __cpuid(result, 0);
+ num = result[0];
+
+ if (num >= 1) {
+ __cpuid(result, 0x00000001);
+ return (result[2] & ((int)1 << 19)) != 0;
+ }
+ return 0;
+}
+
void BLI_hostname_get(char *buffer, size_t bufsize)
{
#ifndef WIN32
diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c
index 9e6ea0bb6ee..724f27f4667 100644
--- a/source/blender/blenlib/intern/winstuff.c
+++ b/source/blender/blenlib/intern/winstuff.c
@@ -172,17 +172,7 @@ void RegisterBlendExtension(void)
BLI_getInstallationDir(InstallDir);
GetSystemDirectory(SysDir, FILE_MAXDIR);
-# ifdef _WIN64
- ThumbHandlerDLL = "BlendThumb64.dll";
-# else
- IsWow64Process(GetCurrentProcess(), &IsWOW64);
- if (IsWOW64 == true) {
- ThumbHandlerDLL = "BlendThumb64.dll";
- }
- else {
- ThumbHandlerDLL = "BlendThumb.dll";
- }
-# endif
+ ThumbHandlerDLL = "BlendThumb.dll";
snprintf(
RegCmd, MAX_PATH * 2, "%s\\regsvr32 /s \"%s\\%s\"", SysDir, InstallDir, ThumbHandlerDLL);
system(RegCmd);
diff --git a/source/blender/blenloader/BLO_blend_defs.h b/source/blender/blenloader/BLO_blend_defs.h
index 0787d054141..fec61605dca 100644
--- a/source/blender/blenloader/BLO_blend_defs.h
+++ b/source/blender/blenloader/BLO_blend_defs.h
@@ -18,7 +18,7 @@
/** \file
* \ingroup blenloader
- * \brief defines for blendfile codes
+ * \brief defines for blend-file codes.
*/
/* INTEGER CODES */
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 8944dfdb711..adf3bf00d48 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -41,7 +41,6 @@ struct UserDef;
struct View3D;
struct ViewLayer;
struct WorkSpace;
-struct bContext;
struct bScreen;
struct wmWindowManager;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 91221ed3740..52d80c0cba1 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -223,7 +223,7 @@
* which keeps large arrays in memory from data-blocks we may not even use.
*
* \note This is disabled when using compression,
- * while zlib supports seek ist's unusably slow, see: T61880.
+ * while zlib supports seek it's unusably slow, see: T61880.
*/
#define USE_BHEAD_READ_ON_DEMAND
@@ -234,7 +234,7 @@
#define USE_GHASH_RESTORE_POINTER
/* Define this to have verbose debug prints. */
-#define USE_DEBUG_PRINT
+//#define USE_DEBUG_PRINT
#ifdef USE_DEBUG_PRINT
# define DEBUG_PRINTF(...) printf(__VA_ARGS__)
@@ -272,13 +272,13 @@ typedef struct BHeadN {
* because ID names are used in lookup tables. */
#define BHEAD_USE_READ_ON_DEMAND(bhead) ((bhead)->code == DATA)
-/* this function ensures that reports are printed,
- * in the case of libraray linking errors this is important!
+/**
+ * This function ensures that reports are printed,
+ * in the case of library linking errors this is important!
*
* bit kludge but better then doubling up on prints,
* we could alternatively have a versions of a report function which forces printing - campbell
*/
-
void blo_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...)
{
char fixed_buf[1024]; /* should be long enough */
@@ -534,7 +534,7 @@ static void split_libdata(ListBase *lb_src, Main **lib_main_array, const uint li
if (id->lib) {
if (((uint)id->lib->temp_index < lib_main_array_len) &&
- /* this check should never fail, just incase 'id->lib' is a dangling pointer. */
+ /* this check should never fail, just in case 'id->lib' is a dangling pointer. */
(lib_main_array[id->lib->temp_index]->curlib == id->lib)) {
Main *mainvar = lib_main_array[id->lib->temp_index];
ListBase *lb_dst = which_libbase(mainvar, GS(id->name));
@@ -2499,16 +2499,13 @@ static void IDP_DirectLinkProperty(IDProperty *prop, int switch_endian, FileData
IDP_DirectLinkIDPArray(prop, switch_endian, fd);
break;
case IDP_DOUBLE:
- /* erg, stupid doubles. since I'm storing them
- * in the same field as int val; val2 in the
- * IDPropertyData struct, they have to deal with
- * endianness specifically
+ /* Workaround for doubles.
+ * They are stored in the same field as `int val, val2` in the IDPropertyData struct,
+ * they have to deal with endianness specifically.
*
- * in theory, val and val2 would've already been swapped
+ * In theory, val and val2 would've already been swapped
* if switch_endian is true, so we have to first unswap
- * them then reswap them as a single 64-bit entity.
- */
-
+ * them then re-swap them as a single 64-bit entity. */
if (switch_endian) {
BLI_endian_switch_int32(&prop->data.val);
BLI_endian_switch_int32(&prop->data.val2);
@@ -4899,21 +4896,13 @@ static void lib_link_mesh(FileData *fd, Main *main)
G_MAIN = gmain;
}
- /*
- * Re-tessellate, even if the polys were just created from tessfaces, this
- * is important because it:
- * - fill the CD_ORIGINDEX layer
- * - gives consistency of tessface between loading from a file and
- * converting an edited BMesh back into a mesh (i.e. it replaces
- * quad tessfaces in a loaded mesh immediately, instead of lazily
- * waiting until edit mode has been entered/exited, making it easier
- * to recognize problems that would otherwise only show up after edits).
- */
-#ifdef USE_TESSFACE_DEFAULT
- BKE_mesh_tessface_calc(me);
-#else
+ /* Deprecated, only kept for conversion. */
BKE_mesh_tessface_clear(me);
-#endif
+
+ /* Moved from do_versions because we need updated polygons for calculating normals. */
+ if (MAIN_VERSION_OLDER(main, 256, 6)) {
+ BKE_mesh_calc_normals(me);
+ }
me->id.tag &= ~LIB_TAG_NEED_LINK;
}
@@ -7719,8 +7708,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
win->addmousemove = true;
win->stereo3d_format = newdataadr(fd, win->stereo3d_format);
- /* multiview always fallback to anaglyph at file opening
- * otherwise quadbuffer saved files can break Blender */
+ /* Multi-view always fallback to anaglyph at file opening
+ * otherwise quad-buffer saved files can break Blender. */
if (win->stereo3d_format) {
win->stereo3d_format->display_mode = S3D_DISPLAY_ANAGLYPH;
}
@@ -9225,7 +9214,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, const int ta
* flags dependency graph does not do animation update to avoid loss of unkeyed changes.,
* which conflicts with undo/redo of changes to animation data itself.
*
- * But for regular file load we clear the flag, since the flags might have been changed sinde
+ * But for regular file load we clear the flag, since the flags might have been changed since
* the version the file has been saved with. */
if (!fd->memfile) {
id->recalc = 0;
@@ -11314,7 +11303,7 @@ static void add_collections_to_scene(Main *mainvar,
}
/* We do not want to force instantiation of indirectly linked collections,
* not even when appending. Users can now easily instantiate collections (and their objects)
- * as needed by themsleves. See T67032. */
+ * as needed by themselves. See T67032. */
else if ((collection->id.tag & LIB_TAG_INDIRECT) == 0) {
bool do_add_collection = (collection->id.tag & LIB_TAG_DOIT) != 0;
if (!do_add_collection) {
diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c
index 6a5cfc45628..ba4dc2d33c7 100644
--- a/source/blender/blenloader/intern/versioning_250.c
+++ b/source/blender/blenloader/intern/versioning_250.c
@@ -2080,11 +2080,12 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
}
}
- if (bmain->versionfile < 256 || (bmain->versionfile == 256 && bmain->subversionfile < 6)) {
- Mesh *me;
-
- for (me = bmain->meshes.first; me; me = me->id.next) {
- BKE_mesh_calc_normals_tessface(me->mvert, me->totvert, me->mface, me->totface, NULL);
+ if (0) {
+ if (bmain->versionfile < 256 || (bmain->versionfile == 256 && bmain->subversionfile < 6)) {
+ for (Mesh *me = bmain->meshes.first; me; me = me->id.next) {
+ /* Vertex normal calculation from legacy 'MFace' has been removed.
+ * update after calculating polygons in file reading code instead. */
+ }
}
}
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index b61692799ed..5010cc8071d 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1748,7 +1748,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
br->falloff_angle = DEG2RADF(80);
br->flag &= ~(BRUSH_FLAG_UNUSED_1 | BRUSH_FLAG_UNUSED_6 | BRUSH_FLAG_UNUSED_7 |
- BRUSH_FLAG_UNUSED_17 | BRUSH_FRONTFACE_FALLOFF);
+ BRUSH_SCENE_SPACING | BRUSH_FRONTFACE_FALLOFF);
}
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 1d2490229da..51c8a0d2a72 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -125,8 +125,8 @@ static void do_version_workspaces_create_from_screens(Main *bmain)
}
if (screen_parent) {
- /* fullscreen with "Back to Previous" option, don't create
- * a new workspace, add layout workspace containing parent */
+ /* Full-screen with "Back to Previous" option, don't create
+ * a new workspace, add layout workspace containing parent. */
workspace = BLI_findstring(
&bmain->workspaces, screen_parent->id.name + 2, offsetof(ID, name) + 2);
}
@@ -406,7 +406,7 @@ static void do_version_layers_to_collections(Main *bmain, Scene *scene)
}
/* Create collections from layers. */
- Collection *collection_master = BKE_collection_master(scene);
+ Collection *collection_master = scene->master_collection;
Collection *collections[20] = {NULL};
for (int layer = 0; layer < 20; layer++) {
@@ -735,13 +735,9 @@ static void do_versions_seq_alloc_transform_and_crop(ListBase *seqbase)
}
/* Return true if there is something to convert. */
-static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree,
- char blend_method,
- GSet *nodegrp_tree_set,
- GSet *nooutput_tree_set)
+static void do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree, char blend_method)
{
bool need_update = false;
- bool do_conversion = false;
/* Iterate backwards from end so we don't encounter newly added links. */
bNodeLink *prevlink;
@@ -754,31 +750,6 @@ static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree,
bNode *tonode = link->tonode;
bNodeSocket *tosock = link->tosock;
- if (nodegrp_tree_set) {
- if (fromnode->type == NODE_GROUP && fromnode->id != NULL) {
- bNodeTree *group_ntree = (bNodeTree *)fromnode->id;
- if (BLI_gset_add(nodegrp_tree_set, group_ntree)) {
- /* Recursive but not convert (blend_method = -1). Conversion happens after. */
- if (!do_versions_material_convert_legacy_blend_mode(
- group_ntree, -1, nodegrp_tree_set, nooutput_tree_set)) {
- /* There is no output to convert in the tree. */
- BLI_gset_add(nooutput_tree_set, group_ntree);
- }
- }
- }
- if (tonode->type == NODE_GROUP && tonode->id != NULL) {
- bNodeTree *group_ntree = (bNodeTree *)tonode->id;
- if (BLI_gset_add(nodegrp_tree_set, group_ntree)) {
- /* Recursive but not convert (blend_method = -1). Conversion happens after. */
- if (!do_versions_material_convert_legacy_blend_mode(
- group_ntree, -1, nodegrp_tree_set, nooutput_tree_set)) {
- /* There is no output to convert in the tree. */
- BLI_gset_add(nooutput_tree_set, group_ntree);
- }
- }
- }
- }
-
if (!(tonode->type == SH_NODE_OUTPUT_MATERIAL && STREQ(tosock->identifier, "Surface"))) {
continue;
}
@@ -788,8 +759,6 @@ static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree,
continue;
}
- do_conversion = true;
-
if (blend_method == 1 /* MA_BM_ADD */) {
nodeRemLink(ntree, link);
@@ -854,11 +823,9 @@ static bool do_versions_material_convert_legacy_blend_mode(bNodeTree *ntree,
if (need_update) {
ntreeUpdateTree(NULL, ntree);
}
-
- return do_conversion;
}
-void do_versions_after_linking_280(Main *bmain, ReportList *reports)
+void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports))
{
bool use_collection_compat_28 = true;
@@ -1259,74 +1226,20 @@ void do_versions_after_linking_280(Main *bmain, ReportList *reports)
* now that we use dualsource blending. */
/* We take care of doing only nodetrees that are always part of materials
* with old blending modes. */
- GSet *ntrees_additive = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- GSet *ntrees_multiply = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- GSet *ntrees_nolegacy = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
- GSet *ntrees_nooutput = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
for (Material *ma = bmain->materials.first; ma; ma = ma->id.next) {
bNodeTree *ntree = ma->nodetree;
if (ma->blend_method == 1 /* MA_BM_ADD */) {
if (ma->use_nodes) {
- do_versions_material_convert_legacy_blend_mode(
- ntree, ma->blend_method, ntrees_additive, ntrees_nooutput);
+ do_versions_material_convert_legacy_blend_mode(ntree, 1 /* MA_BM_ADD */);
}
ma->blend_method = MA_BM_BLEND;
}
else if (ma->blend_method == 2 /* MA_BM_MULTIPLY */) {
if (ma->use_nodes) {
- do_versions_material_convert_legacy_blend_mode(
- ntree, ma->blend_method, ntrees_multiply, ntrees_nooutput);
+ do_versions_material_convert_legacy_blend_mode(ntree, 2 /* MA_BM_MULTIPLY */);
}
ma->blend_method = MA_BM_BLEND;
}
- else {
- /* Still tag the group nodes as not using legacy blend modes. */
- if (ma->use_nodes) {
- do_versions_material_convert_legacy_blend_mode(
- ntree, -1, ntrees_nolegacy, ntrees_nooutput);
- }
- }
- }
- GHashIterState iter = {0};
- bNodeTree *ntree;
- /* Remove trees that have no output nodes.
- * This is done separately to avoid infinite recursion. */
- while (BLI_gset_pop(ntrees_nooutput, (GSetIterState *)&iter, (void **)&ntree)) {
- BLI_gset_remove(ntrees_additive, ntree, NULL);
- BLI_gset_remove(ntrees_multiply, ntree, NULL);
- BLI_gset_remove(ntrees_nolegacy, ntree, NULL);
- }
- BLI_gset_free(ntrees_nooutput, NULL);
- /* Remove group nodetree that are used by material using non-legacy blend mode. */
- GHashIterState iter_rm = {0};
- bool error = false;
- while (BLI_gset_pop(ntrees_nolegacy, (GSetIterState *)&iter_rm, (void **)&ntree)) {
- if (BLI_gset_remove(ntrees_additive, ntree, NULL)) {
- error = true;
- }
- if (BLI_gset_remove(ntrees_multiply, ntree, NULL)) {
- error = true;
- }
- }
- BLI_gset_free(ntrees_nolegacy, NULL);
- /* Convert remaining group nodetree. */
- GHashIterState iter_add = {0};
- GHashIterState iter_mul = {0};
- while (BLI_gset_pop(ntrees_additive, (GSetIterState *)&iter_add, (void **)&ntree)) {
- do_versions_material_convert_legacy_blend_mode(ntree, 1 /* MA_BM_ADD */, NULL, NULL);
- }
- while (BLI_gset_pop(ntrees_multiply, (GSetIterState *)&iter_mul, (void **)&ntree)) {
- do_versions_material_convert_legacy_blend_mode(ntree, 2 /* MA_BM_MULTIPLY */, NULL, NULL);
- }
- BLI_gset_free(ntrees_additive, NULL);
- BLI_gset_free(ntrees_multiply, NULL);
-
- if (error) {
- BKE_report(reports, RPT_ERROR, "Eevee material conversion problem. Error in console");
- printf(
- "One or more group nodetrees containing a material output were found"
- " in both a material using deprecated blend mode and a normal one.\n"
- "Nothing in these nodetrees was changed and manual update is required.\n");
}
}
}
@@ -3792,8 +3705,7 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
- {
- /* Versioning code until next subversion bump goes here. */
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
if (U.view_rotate_sensitivity_turntable == 0) {
U.view_rotate_sensitivity_turntable = DEG2RADF(0.4f);
U.view_rotate_sensitivity_trackball = 1.0f;
@@ -3808,6 +3720,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
ar->alignment = RGN_ALIGN_RIGHT;
}
}
+ /* Mark outliners as dirty for syncing and enable synced selection */
+ if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOutliner *soutliner = (SpaceOutliner *)sl;
+ soutliner->sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL;
+ soutliner->flag |= SO_SYNC_SELECT;
+ }
}
}
}
@@ -3817,4 +3735,69 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 4)) {
+ ID *id;
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ bNodeTree *ntree = ntreeFromID(id);
+ if (ntree) {
+ ntree->id.flag |= LIB_PRIVATE_DATA;
+ }
+ }
+ FOREACH_MAIN_ID_END;
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 5)) {
+ for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
+ if (br->ob_mode & OB_MODE_SCULPT && br->normal_radius_factor == 0.0f) {
+ br->normal_radius_factor = 0.5f;
+ }
+ }
+
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ /* Older files do not have a master collection, which is then added through
+ * `BKE_collection_master_add()`, so everything is fine. */
+ if (scene->master_collection != NULL) {
+ scene->master_collection->id.flag |= LIB_PRIVATE_DATA;
+ }
+ }
+ }
+
+ {
+ /* Versioning code until next subversion bump goes here. */
+
+ for (bScreen *screen = bmain->screens.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_FILE) {
+ SpaceFile *sfile = (SpaceFile *)sl;
+ ListBase *regionbase = (sl == sa->spacedata.first) ? &sa->regionbase : &sl->regionbase;
+ ARegion *ar_ui = do_versions_find_region(regionbase, RGN_TYPE_UI);
+ ARegion *ar_header = do_versions_find_region(regionbase, RGN_TYPE_HEADER);
+ ARegion *ar_toolprops = do_versions_find_region_or_null(regionbase,
+ RGN_TYPE_TOOL_PROPS);
+
+ /* Reinsert UI region so that it spawns entire area width */
+ BLI_remlink(regionbase, ar_ui);
+ BLI_insertlinkafter(regionbase, ar_header, ar_ui);
+
+ ar_ui->flag |= RGN_FLAG_DYNAMIC_SIZE;
+
+ if (ar_toolprops && (ar_toolprops->alignment == (RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV))) {
+ SpaceType *stype = BKE_spacetype_from_id(sl->spacetype);
+
+ /* Remove empty region at old location. */
+ BLI_assert(sfile->op == NULL);
+ BKE_area_region_free(stype, ar_toolprops);
+ BLI_freelinkN(regionbase, ar_toolprops);
+ }
+
+ if (sfile->params) {
+ sfile->params->details_flags |= FILE_DETAILS_SIZE | FILE_DETAILS_DATETIME;
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_cycles.c b/source/blender/blenloader/intern/versioning_cycles.c
index cebe15e2719..a3e9b8dc206 100644
--- a/source/blender/blenloader/intern/versioning_cycles.c
+++ b/source/blender/blenloader/intern/versioning_cycles.c
@@ -26,6 +26,7 @@
#include "BLI_math.h"
#include "BLI_string.h"
+#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "DNA_color_types.h"
@@ -44,6 +45,11 @@
#include "BLO_readfile.h"
#include "readfile.h"
+static bool socket_is_used(bNodeSocket *sock)
+{
+ return sock->flag & SOCK_IN_USE;
+}
+
static float *cycles_node_socket_float_value(bNodeSocket *socket)
{
bNodeSocketValueFloat *socket_data = socket->default_value;
@@ -56,6 +62,12 @@ static float *cycles_node_socket_rgba_value(bNodeSocket *socket)
return socket_data->value;
}
+static float *cycles_node_socket_vector_value(bNodeSocket *socket)
+{
+ bNodeSocketValueVector *socket_data = socket->default_value;
+ return socket_data->value;
+}
+
static IDProperty *cycles_properties_from_ID(ID *id)
{
IDProperty *idprop = IDP_GetProperties(id, false);
@@ -185,7 +197,7 @@ static void square_roughness_node_insert(bNodeTree *ntree)
/* Add sqrt node. */
bNode *node = nodeAddStaticNode(NULL, ntree, SH_NODE_MATH);
- node->custom1 = NODE_MATH_POW;
+ node->custom1 = NODE_MATH_POWER;
node->locx = 0.5f * (fromnode->locx + tonode->locx);
node->locy = 0.5f * (fromnode->locy + tonode->locy);
@@ -385,6 +397,365 @@ static void light_emission_unify(Light *light, const char *engine)
}
}
+/* The B input of the Math node is no longer used for single-operand operators.
+ * Previously, if the B input was linked and the A input was not, the B input
+ * was used as the input of the operator. To correct this, we move the link
+ * from B to A if B is linked and A is not.
+ */
+static void update_math_node_single_operand_operators(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_MATH) {
+ if (ELEM(node->custom1,
+ NODE_MATH_SQRT,
+ NODE_MATH_CEIL,
+ NODE_MATH_SINE,
+ NODE_MATH_ROUND,
+ NODE_MATH_FLOOR,
+ NODE_MATH_COSINE,
+ NODE_MATH_ARCSINE,
+ NODE_MATH_TANGENT,
+ NODE_MATH_ABSOLUTE,
+ NODE_MATH_FRACTION,
+ NODE_MATH_ARCCOSINE,
+ NODE_MATH_ARCTANGENT)) {
+ bNodeSocket *sockA = BLI_findlink(&node->inputs, 0);
+ bNodeSocket *sockB = BLI_findlink(&node->inputs, 1);
+ if (!sockA->link && sockB->link) {
+ nodeAddLink(ntree, sockB->link->fromnode, sockB->link->fromsock, node, sockA);
+ nodeRemLink(ntree, sockB->link);
+ need_update = true;
+ }
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* The Value output of the Vector Math node is no longer available in the Add
+ * and Subtract operators. Previously, this Value output was computed from the
+ * Vector output V as follows:
+ *
+ * Value = (abs(V.x) + abs(V.y) + abs(V.z)) / 3
+ *
+ * Or more compactly using vector operators:
+ *
+ * Value = dot(abs(V), (1 / 3, 1 / 3, 1 / 3))
+ *
+ * To correct this, if the Value output was used, we are going to compute
+ * it using the second equation by adding an absolute and a dot node, and
+ * then connect them appropriately.
+ */
+static void update_vector_math_node_add_and_subtract_operators(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
+ if (socket_is_used(sockOutValue) &&
+ ELEM(node->custom1, NODE_VECTOR_MATH_ADD, NODE_VECTOR_MATH_SUBTRACT)) {
+
+ bNode *absNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ absNode->custom1 = NODE_VECTOR_MATH_ABSOLUTE;
+ absNode->locx = node->locx + node->width + 20.0f;
+ absNode->locy = node->locy;
+
+ bNode *dotNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ dotNode->custom1 = NODE_VECTOR_MATH_DOT_PRODUCT;
+ dotNode->locx = absNode->locx + absNode->width + 20.0f;
+ dotNode->locy = absNode->locy;
+ bNodeSocket *sockDotB = BLI_findlink(&dotNode->inputs, 1);
+ bNodeSocket *sockDotOutValue = nodeFindSocket(dotNode, SOCK_OUT, "Value");
+ copy_v3_fl(cycles_node_socket_vector_value(sockDotB), 1 / 3.0f);
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutValue) {
+ nodeAddLink(ntree, dotNode, sockDotOutValue, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+
+ bNodeSocket *sockAbsA = BLI_findlink(&absNode->inputs, 0);
+ bNodeSocket *sockDotA = BLI_findlink(&dotNode->inputs, 0);
+ bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ bNodeSocket *sockAbsOutVector = nodeFindSocket(absNode, SOCK_OUT, "Vector");
+
+ nodeAddLink(ntree, node, sockOutVector, absNode, sockAbsA);
+ nodeAddLink(ntree, absNode, sockAbsOutVector, dotNode, sockDotA);
+
+ need_update = true;
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* The Vector output of the Vector Math node is no longer available in the Dot
+ * Product operator. Previously, this Vector was always zero initialized. To
+ * correct this, we zero out any socket the Vector Output was connected to.
+ */
+static void update_vector_math_node_dot_product_operator(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ if (socket_is_used(sockOutVector) && node->custom1 == NODE_VECTOR_MATH_DOT_PRODUCT) {
+ LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutVector) {
+ switch (link->tosock->type) {
+ case SOCK_FLOAT:
+ *cycles_node_socket_float_value(link->tosock) = 0.0f;
+ break;
+ case SOCK_VECTOR:
+ copy_v3_fl(cycles_node_socket_vector_value(link->tosock), 0.0f);
+ break;
+ case SOCK_RGBA:
+ copy_v4_fl(cycles_node_socket_rgba_value(link->tosock), 0.0f);
+ break;
+ }
+ nodeRemLink(ntree, link);
+ }
+ }
+ need_update = true;
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* Previously, the Vector output of the cross product operator was normalized.
+ * To correct this, a Normalize node is added to normalize the output if used.
+ * Moreover, the Value output was removed. This Value was equal to the length
+ * of the cross product. To correct this, a Length node is added if needed.
+ */
+static void update_vector_math_node_cross_product_operator(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ if (node->custom1 == NODE_VECTOR_MATH_CROSS_PRODUCT) {
+ bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ if (socket_is_used(sockOutVector)) {
+ bNode *normalizeNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ normalizeNode->custom1 = NODE_VECTOR_MATH_NORMALIZE;
+ normalizeNode->locx = node->locx + node->width + 20.0f;
+ normalizeNode->locy = node->locy;
+ bNodeSocket *sockNormalizeOut = nodeFindSocket(normalizeNode, SOCK_OUT, "Vector");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutVector) {
+ nodeAddLink(ntree, normalizeNode, sockNormalizeOut, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ bNodeSocket *sockNormalizeA = BLI_findlink(&normalizeNode->inputs, 0);
+ nodeAddLink(ntree, node, sockOutVector, normalizeNode, sockNormalizeA);
+
+ need_update = true;
+ }
+
+ bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
+ if (socket_is_used(sockOutValue)) {
+ bNode *lengthNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
+ lengthNode->locx = node->locx + node->width + 20.0f;
+ if (socket_is_used(sockOutVector)) {
+ lengthNode->locy = node->locy - lengthNode->height - 20.0f;
+ }
+ else {
+ lengthNode->locy = node->locy;
+ }
+ bNodeSocket *sockLengthOut = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutValue) {
+ nodeAddLink(ntree, lengthNode, sockLengthOut, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
+ nodeAddLink(ntree, node, sockOutVector, lengthNode, sockLengthA);
+
+ need_update = true;
+ }
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* The Value output of the Vector Math node is no longer available in the
+ * Normalize operator. This Value output was equal to the length of the
+ * the input vector A. To correct this, we either add a Length node or
+ * convert the Normalize node into a Length node, depending on if the
+ * Vector output is needed.
+ */
+static void update_vector_math_node_normalize_operator(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
+ if (node->custom1 == NODE_VECTOR_MATH_NORMALIZE && socket_is_used(sockOutValue)) {
+ bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ if (socket_is_used(sockOutVector)) {
+ bNode *lengthNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
+ lengthNode->locx = node->locx + node->width + 20.0f;
+ lengthNode->locy = node->locy;
+ bNodeSocket *sockLengthValue = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutValue) {
+ nodeAddLink(ntree, lengthNode, sockLengthValue, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ bNodeSocket *sockA = BLI_findlink(&node->inputs, 0);
+ bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
+ if (sockA->link) {
+ bNodeLink *link = sockA->link;
+ nodeAddLink(ntree, link->fromnode, link->fromsock, lengthNode, sockLengthA);
+ }
+ else {
+ copy_v3_v3(cycles_node_socket_vector_value(sockLengthA),
+ cycles_node_socket_vector_value(sockA));
+ }
+
+ need_update = true;
+ }
+ else {
+ node->custom1 = NODE_VECTOR_MATH_LENGTH;
+ }
+ }
+ }
+ }
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
+/* The Vector Math operator types didn't have an enum, but rather, their
+ * values were hard coded into the code. After the enum was created and
+ * after more vector operators were added, the hard coded values needs
+ * to be remapped to their correct enum values. To fix this, we remap
+ * the values according to the following rules:
+ *
+ * Dot Product Operator : 3 -> 7
+ * Normalize Operator : 5 -> 11
+ *
+ * Additionally, since the Average operator was removed, it is assigned
+ * a value of -1 just to be identified later in the versioning code:
+ *
+ * Average Operator : 2 -> -1
+ *
+ */
+static void update_vector_math_node_operators_enum_mapping(bNodeTree *ntree)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ switch (node->custom1) {
+ case 2:
+ node->custom1 = -1;
+ break;
+ case 3:
+ node->custom1 = 7;
+ break;
+ case 5:
+ node->custom1 = 11;
+ break;
+ }
+ }
+ }
+}
+
+/* The Average operator is no longer available in the Vector Math node.
+ * The Vector output was equal to the normalized sum of input vectors while
+ * the Value output was equal to the length of the sum of input vectors.
+ * To correct this, we convert the node into an Add node and add a length
+ * node or a normalize node if needed.
+ */
+static void update_vector_math_node_average_operator(bNodeTree *ntree)
+{
+ bool need_update = false;
+
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == SH_NODE_VECTOR_MATH) {
+ /* See update_vector_math_node_operators_enum_mapping. */
+ if (node->custom1 == -1) {
+ node->custom1 = NODE_VECTOR_MATH_ADD;
+ bNodeSocket *sockOutVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ if (socket_is_used(sockOutVector)) {
+ bNode *normalizeNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ normalizeNode->custom1 = NODE_VECTOR_MATH_NORMALIZE;
+ normalizeNode->locx = node->locx + node->width + 20.0f;
+ normalizeNode->locy = node->locy;
+ bNodeSocket *sockNormalizeOut = nodeFindSocket(normalizeNode, SOCK_OUT, "Vector");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutVector) {
+ nodeAddLink(ntree, normalizeNode, sockNormalizeOut, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ bNodeSocket *sockNormalizeA = BLI_findlink(&normalizeNode->inputs, 0);
+ nodeAddLink(ntree, node, sockOutVector, normalizeNode, sockNormalizeA);
+
+ need_update = true;
+ }
+
+ bNodeSocket *sockOutValue = nodeFindSocket(node, SOCK_OUT, "Value");
+ if (socket_is_used(sockOutValue)) {
+ bNode *lengthNode = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
+ lengthNode->custom1 = NODE_VECTOR_MATH_LENGTH;
+ lengthNode->locx = node->locx + node->width + 20.0f;
+ if (socket_is_used(sockOutVector)) {
+ lengthNode->locy = node->locy - lengthNode->height - 20.0f;
+ }
+ else {
+ lengthNode->locy = node->locy;
+ }
+ bNodeSocket *sockLengthOut = nodeFindSocket(lengthNode, SOCK_OUT, "Value");
+
+ LISTBASE_FOREACH_BACKWARD_MUTABLE (bNodeLink *, link, &ntree->links) {
+ if (link->fromsock == sockOutValue) {
+ nodeAddLink(ntree, lengthNode, sockLengthOut, link->tonode, link->tosock);
+ nodeRemLink(ntree, link);
+ }
+ }
+ bNodeSocket *sockLengthA = BLI_findlink(&lengthNode->inputs, 0);
+ nodeAddLink(ntree, node, sockOutVector, lengthNode, sockLengthA);
+
+ need_update = true;
+ }
+ }
+ }
+ }
+
+ if (need_update) {
+ ntreeUpdateTree(NULL, ntree);
+ }
+}
+
void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bmain)
{
/* Particle shape shared with Eevee. */
@@ -417,6 +788,15 @@ void blo_do_versions_cycles(FileData *UNUSED(fd), Library *UNUSED(lib), Main *bm
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_vector_math_node_operators_enum_mapping(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
}
void do_versions_after_linking_cycles(Main *bmain)
@@ -526,4 +906,26 @@ void do_versions_after_linking_cycles(Main *bmain)
}
}
}
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 2)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_math_node_single_operand_operators(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 281, 3)) {
+ FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
+ if (ntree->type == NTREE_SHADER) {
+ update_vector_math_node_add_and_subtract_operators(ntree);
+ update_vector_math_node_dot_product_operator(ntree);
+ update_vector_math_node_cross_product_operator(ntree);
+ update_vector_math_node_normalize_operator(ntree);
+ update_vector_math_node_average_operator(ntree);
+ }
+ }
+ FOREACH_NODETREE_END;
+ }
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index fa69892584a..fa22fd46068 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -329,6 +329,14 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
BLI_strncpy(screen->id.name + 2, workspace->id.name + 2, sizeof(screen->id.name) - 2);
BLI_libblock_ensure_unique_name(bmain, screen->id.name);
}
+
+ /* For some reason we have unused screens, needed until re-saving.
+ * Clear unused layouts because they're visible in the outliner & Python API. */
+ LISTBASE_FOREACH_MUTABLE (WorkSpaceLayout *, layout_iter, &workspace->layouts) {
+ if (layout != layout_iter) {
+ BKE_workspace_layout_remove(bmain, workspace, layout_iter);
+ }
+ }
}
/* Scenes */
diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c
index e987a623d0b..67b8ce1d0de 100644
--- a/source/blender/blenloader/intern/versioning_userdef.c
+++ b/source/blender/blenloader/intern/versioning_userdef.c
@@ -141,10 +141,16 @@ static void do_versions_theme(const UserDef *userdef, bTheme *btheme)
FROM_DEFAULT_V4_UCHAR(space_outliner.row_alternate);
}
+ if (!USER_VERSION_ATLEAST(281, 3)) {
+ FROM_DEFAULT_V4_UCHAR(space_outliner.selected_highlight);
+ FROM_DEFAULT_V4_UCHAR(space_outliner.active);
+ }
+
/**
* Include next version bump.
*/
{
+ FROM_DEFAULT_V4_UCHAR(space_file.execution_buts);
}
#undef FROM_DEFAULT_V4_UCHAR
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index d8889db7f2d..e81fa9fd2ff 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1143,9 +1143,12 @@ typedef struct RenderInfo {
char scene_name[MAX_ID_NAME - 2];
} RenderInfo;
-/* was for historic render-deamon feature,
- * now write because it can be easily extracted without
- * reading the whole blend file */
+/**
+ * This was originally added for the historic render-daemon feature,
+ * now write because it can be easily extracted without reading the whole blend file.
+ *
+ * See: `release/scripts/modules/blend_render_info.py`
+ */
static void write_renderinfo(WriteData *wd, Main *mainvar)
{
bScreen *curscreen;
diff --git a/source/blender/blentranslation/msgfmt/msgfmt.c b/source/blender/blentranslation/msgfmt/msgfmt.c
index 215c92f87de..4691d791301 100644
--- a/source/blender/blentranslation/msgfmt/msgfmt.c
+++ b/source/blender/blentranslation/msgfmt/msgfmt.c
@@ -24,7 +24,7 @@
*
* Generate binary message catalog from textual translation description.
*
- * This program converts a textual Uniforum-style message catalog (.po file)
+ * This program converts a textual Uniform-style message catalog (.po file)
* into a binary GNU catalog (.mo file).
* This is essentially the same function as the GNU msgfmt program,
* however, it is a simpler implementation.
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 5aec59ccd5d..788edc348d9 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -870,9 +870,11 @@ void BM_editselection_normal(BMEditSelection *ese, float r_normal[3])
}
}
-/* Calculate a plane that is rightangles to the edge/vert/faces normal
+/**
+ * Calculate a plane that is right angles to the edge/vert/faces normal
* also make the plane run along an axis that is related to the geometry,
- * because this is used for the gizmos Y axis. */
+ * because this is used for the gizmos Y axis.
+ */
void BM_editselection_plane(BMEditSelection *ese, float r_plane[3])
{
if (ese->htype == BM_VERT) {
diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c
index 2000689b496..9bab959f0a2 100644
--- a/source/blender/bmesh/intern/bmesh_mesh_conv.c
+++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c
@@ -422,7 +422,7 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar
/* don't use 'j' since we may have skipped some faces, hence some loops. */
BM_elem_index_set(l_iter, totloops++); /* set_ok */
- /* Save index of correspsonding MLoop */
+ /* Save index of corresponding #MLoop. */
CustomData_to_bmesh_block(&me->ldata, &bm->ldata, j++, &l_iter->head.data, true);
} while ((l_iter = l_iter->next) != l_first);
diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c
index b9f0bcc05f0..7086cea1ace 100644
--- a/source/blender/bmesh/intern/bmesh_opdefines.c
+++ b/source/blender/bmesh/intern/bmesh_opdefines.c
@@ -369,28 +369,6 @@ static BMOpDefine bmo_remove_doubles_def = {
};
/*
- * Auto Merge.
- *
- * Finds groups of vertices closer then **dist** and merges them together,
- * using the weld verts bmop. The merges must go from a vert not in
- * **verts** to one in **verts**.
- */
-static BMOpDefine bmo_automerge_def = {
- "automerge",
- /* slots_in */
- {{"verts", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT}}, /* input verts */
- {"dist", BMO_OP_SLOT_FLT}, /* maximum distance */
- {{'\0'}},
- },
- {{{'\0'}}}, /* no output */
- bmo_automerge_exec,
- (BMO_OPTYPE_FLAG_UNTAN_MULTIRES |
- BMO_OPTYPE_FLAG_NORMALS_CALC |
- BMO_OPTYPE_FLAG_SELECT_FLUSH |
- BMO_OPTYPE_FLAG_SELECT_VALIDATE),
-};
-
-/*
* Collapse Connected.
*
* Collapses connected vertices
@@ -2073,7 +2051,6 @@ static BMOpDefine bmo_symmetrize_def = {
/* clang-format on */
const BMOpDefine *bmo_opdefines[] = {
- &bmo_automerge_def,
&bmo_average_vert_facedata_def,
&bmo_beautify_fill_def,
&bmo_bevel_def,
diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h
index 8658f6c233c..137c5aa338e 100644
--- a/source/blender/bmesh/intern/bmesh_operators_private.h
+++ b/source/blender/bmesh/intern/bmesh_operators_private.h
@@ -24,7 +24,6 @@
struct BMOperator;
struct BMesh;
-void bmo_automerge_exec(BMesh *bm, BMOperator *op);
void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op);
void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op);
void bmo_bevel_exec(BMesh *bm, BMOperator *op);
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index dc839054987..915ad6bf5c4 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -483,7 +483,7 @@ void BM_face_calc_tangent_edge_diagonal(const BMFace *f, float r_tangent[3])
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- /* incase of degenerate faces */
+ /* In case of degenerate faces. */
zero_v3(r_tangent);
/* warning: O(n^2) loop here, take care! */
@@ -520,7 +520,7 @@ void BM_face_calc_tangent_vert_diagonal(const BMFace *f, float r_tangent[3])
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- /* incase of degenerate faces */
+ /* In case of degenerate faces. */
zero_v3(r_tangent);
/* warning: O(n^2) loop here, take care! */
diff --git a/source/blender/bmesh/intern/bmesh_query.c b/source/blender/bmesh/intern/bmesh_query.c
index 4a47bcccb25..219bec15e5b 100644
--- a/source/blender/bmesh/intern/bmesh_query.c
+++ b/source/blender/bmesh/intern/bmesh_query.c
@@ -207,6 +207,34 @@ bool BM_vert_pair_share_face_check_cb(BMVert *v_a,
return false;
}
+BMFace *BM_vert_pair_shared_face_cb(BMVert *v_a,
+ BMVert *v_b,
+ const bool allow_adjacent,
+ bool (*callback)(BMFace *, BMLoop *, BMLoop *, void *userdata),
+ void *user_data,
+ BMLoop **r_l_a,
+ BMLoop **r_l_b)
+{
+ if (v_a->e && v_b->e) {
+ BMIter iter;
+ BMLoop *l_a, *l_b;
+
+ BM_ITER_ELEM (l_a, &iter, v_a, BM_LOOPS_OF_VERT) {
+ BMFace *f = l_a->f;
+ l_b = BM_face_vert_share_loop(f, v_b);
+ if (l_b && (allow_adjacent || !BM_loop_is_adjacent(l_a, l_b)) &&
+ callback(f, l_a, l_b, user_data)) {
+ *r_l_a = l_a;
+ *r_l_b = l_b;
+
+ return f;
+ }
+ }
+ }
+
+ return NULL;
+}
+
/**
* Given 2 verts, find the smallest face they share and give back both loops.
*/
@@ -1542,7 +1570,7 @@ float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon_sq,
/**
* #BM_loop_calc_face_normal_safe_ex with pre-defined sane epsilon.
*
- * Since this doesn't scale baed on triangle size, fixed value works well.
+ * Since this doesn't scale based on triangle size, fixed value works well.
*/
float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
{
diff --git a/source/blender/bmesh/intern/bmesh_query.h b/source/blender/bmesh/intern/bmesh_query.h
index e96984490c0..3a864fbb5dd 100644
--- a/source/blender/bmesh/intern/bmesh_query.h
+++ b/source/blender/bmesh/intern/bmesh_query.h
@@ -62,6 +62,13 @@ bool BM_vert_pair_share_face_check_cb(BMVert *v_a,
bool (*test_fn)(BMFace *f, void *user_data),
void *user_data) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL(1, 2, 3);
+BMFace *BM_vert_pair_shared_face_cb(BMVert *v_a,
+ BMVert *v_b,
+ const bool allow_adjacent,
+ bool (*callback)(BMFace *, BMLoop *, BMLoop *, void *userdata),
+ void *user_data,
+ BMLoop **r_l_a,
+ BMLoop **r_l_b) ATTR_NONNULL(1, 2, 4, 6, 7);
BMFace *BM_vert_pair_share_face_by_len(BMVert *v_a,
BMVert *v_b,
BMLoop **r_l_a,
diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c
index ade6fdfcbed..f317c59b8d1 100644
--- a/source/blender/bmesh/intern/bmesh_walkers_impl.c
+++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c
@@ -648,7 +648,7 @@ static void *bmw_ConnectedVertexWalker_step(BMWalker *walker)
* \note that this doesn't work on non-manifold geometry.
* it might be better to rewrite this to extract
* boundary info from the island walker, rather then directly walking
- * over the boundary. raises an error if it encounters nonmanifold geometry.
+ * over the boundary. raises an error if it encounters non-manifold geometry.
*
* \todo Add restriction flag/callback for wire edges.
*/
diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c
index f23c420295b..1570c802bee 100644
--- a/source/blender/bmesh/operators/bmo_inset.c
+++ b/source/blender/bmesh/operators/bmo_inset.c
@@ -588,7 +588,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op)
/* tag if boundary is enabled */
(use_boundary && BM_edge_is_boundary(e) && BM_elem_flag_test(e->l->f, BM_ELEM_TAG)) ||
- /* tag if edge is an interior edge inbetween a tagged and untagged face */
+ /* tag if edge is an interior edge in between a tagged and untagged face */
(bm_edge_is_mixed_face_tag(e->l))) {
/* tag */
BM_elem_flag_enable(e->v1, BM_ELEM_TAG);
diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c
index d783842c017..1d28d8223cd 100644
--- a/source/blender/bmesh/operators/bmo_removedoubles.c
+++ b/source/blender/bmesh/operators/bmo_removedoubles.c
@@ -706,34 +706,3 @@ void bmo_find_doubles_exec(BMesh *bm, BMOperator *op)
slot_targetmap_out = BMO_slot_get(op->slots_out, "targetmap.out");
bmesh_find_doubles_common(bm, op, op, slot_targetmap_out);
}
-
-void bmo_automerge_exec(BMesh *bm, BMOperator *op)
-{
- BMOperator findop, weldop;
- BMIter viter;
- BMVert *v;
-
- /* The "verts" input sent to this op is the set of verts that
- * can be merged away into any other verts. Mark all other verts
- * as VERT_KEEP. */
- BMO_slot_buffer_flag_enable(bm, op->slots_in, "verts", BM_VERT, VERT_IN);
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- if (!BMO_vert_flag_test(bm, v, VERT_IN)) {
- BMO_vert_flag_enable(bm, v, VERT_KEEP);
- }
- }
-
- /* Search for doubles among all vertices, but only merge non-VERT_KEEP
- * vertices into VERT_KEEP vertices. */
- BMO_op_initf(bm, &findop, op->flag, "find_doubles verts=%av keep_verts=%fv", VERT_KEEP);
- BMO_slot_copy(op, slots_in, "dist", &findop, slots_in, "dist");
- BMO_op_exec(bm, &findop);
-
- /* weld the vertices */
- BMO_op_init(bm, &weldop, op->flag, "weld_verts");
- BMO_slot_copy(&findop, slots_out, "targetmap.out", &weldop, slots_in, "targetmap");
- BMO_op_exec(bm, &weldop);
-
- BMO_op_finish(bm, &findop);
- BMO_op_finish(bm, &weldop);
-}
diff --git a/source/blender/bmesh/tools/bmesh_beautify.c b/source/blender/bmesh/tools/bmesh_beautify.c
index 5d511374989..dabdbc3c97a 100644
--- a/source/blender/bmesh/tools/bmesh_beautify.c
+++ b/source/blender/bmesh/tools/bmesh_beautify.c
@@ -199,7 +199,7 @@ static float bm_edge_calc_rotate_beauty__area(const float v1[3],
* Allowing to rotate out of a degenerate state can flip the faces
* (when performed iteratively).
*/
- return BLI_polyfill_beautify_quad_rotate_calc_ex(v1_xy, v2_xy, v3_xy, v4_xy, true);
+ return BLI_polyfill_beautify_quad_rotate_calc_ex(v1_xy, v2_xy, v3_xy, v4_xy, true, NULL);
} while (false);
return FLT_MAX;
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 94935f2090b..797e2ca864e 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -3122,6 +3122,7 @@ static void adjust_offsets(BevelParams *bp, BMesh *bm)
}
if (!iscycle) {
/* right->left direction, changing vchainstart at each step */
+ v->adjchain = NULL;
v = vchainstart;
bvcur = bv;
do {
diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
index e32a9334343..198b4c8e76b 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c
@@ -363,7 +363,7 @@ static void bm_decim_build_edge_cost(BMesh *bm,
struct KD_Symmetry_Data {
/* pre-flipped coords */
float e_v1_co[3], e_v2_co[3];
- /* Use to compare the correct endpoints incase v1/v2 are swapped */
+ /* Use to compare the correct endpoints in case v1/v2 are swapped. */
float e_dir[3];
int e_found_index;
@@ -1371,8 +1371,8 @@ void BM_mesh_decimate_collapse(BMesh *bm,
/* handy to detect corruptions elsewhere */
BLI_assert(BM_elem_index_get(e) < tot_edge_orig);
- /* under normal conditions wont be accessed again,
- * but NULL just incase so we don't use freed node */
+ /* Under normal conditions wont be accessed again,
+ * but NULL just in case so we don't use freed node. */
eheap_table[BM_elem_index_get(e)] = NULL;
bm_decim_edge_collapse(bm,
diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
index 27b4fa15f26..2cc86a7c93f 100644
--- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
+++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c
@@ -231,7 +231,7 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool
if (BMO_vert_flag_test(bm, v, ELE_VERT_TAG))
#endif
{
- /* check again incase the topology changed */
+ /* Check again in case the topology changed. */
if (bm_vert_dissolve_fan_test(v)) {
v_first = v;
}
diff --git a/source/blender/bmesh/tools/bmesh_region_match.c b/source/blender/bmesh/tools/bmesh_region_match.c
index 943f7532960..c30992fa296 100644
--- a/source/blender/bmesh/tools/bmesh_region_match.c
+++ b/source/blender/bmesh/tools/bmesh_region_match.c
@@ -1099,7 +1099,7 @@ static BMEdge *bm_face_region_pivot_edge_find(BMFace **faces_region,
}
}
else {
- /* use incase (depth == 0), no interior verts */
+ /* Use in case (depth == 0), no interior verts. */
e_pivot_fallback = e;
}
} while ((l_iter = l_iter->next) != l_first);
diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h
index 27474cc2b58..2be2dadeeeb 100644
--- a/source/blender/collada/AnimationExporter.h
+++ b/source/blender/collada/AnimationExporter.h
@@ -78,8 +78,6 @@ extern "C" {
#include <map>
#include <algorithm> // std::find
-struct Depsgraph;
-
typedef enum BC_animation_source_type {
BC_SOURCE_TYPE_VALUE,
BC_SOURCE_TYPE_ANGLE,
diff --git a/source/blender/collada/AnimationImporter.cpp b/source/blender/collada/AnimationImporter.cpp
index 54177560eb5..79593f07383 100644
--- a/source/blender/collada/AnimationImporter.cpp
+++ b/source/blender/collada/AnimationImporter.cpp
@@ -733,7 +733,7 @@ void AnimationImporter::Assign_float_animations(const COLLADAFW::UniqueId &listi
* Reason: old blender versions stored spot_size in radians (was a bug)
*/
if (this->import_from_version == "" ||
- BLI_natstrcmp(this->import_from_version.c_str(), "2.69.10") != -1) {
+ BLI_strcasecmp_natural(this->import_from_version.c_str(), "2.69.10") != -1) {
fcurve_deg_to_rad(fcu);
}
}
diff --git a/source/blender/collada/CMakeLists.txt b/source/blender/collada/CMakeLists.txt
index 5f28ca4ffbb..40762db759e 100644
--- a/source/blender/collada/CMakeLists.txt
+++ b/source/blender/collada/CMakeLists.txt
@@ -28,10 +28,7 @@ FIND_FILE(OPENCOLLADA_ANIMATION_CLIP
)
IF(OPENCOLLADA_ANIMATION_CLIP)
- message(STATUS "Found opencollada: ${OPENCOLLADA_ANIMATION_CLIP} ")
add_definitions(-DWITH_OPENCOLLADA_ANIMATION_CLIP)
-ELSE()
- message(STATUS "opencollada: Build without animation clip support")
ENDIF()
set(INC
diff --git a/source/blender/collada/ControllerExporter.h b/source/blender/collada/ControllerExporter.h
index 200f8431f62..ce2ed9fe453 100644
--- a/source/blender/collada/ControllerExporter.h
+++ b/source/blender/collada/ControllerExporter.h
@@ -47,7 +47,6 @@
#include "BKE_key.h"
-struct Depsgraph;
class SceneExporter;
class ControllerExporter : public COLLADASW::LibraryControllers,
diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h
index 7262784db82..8c7a38fc407 100644
--- a/source/blender/collada/GeometryExporter.h
+++ b/source/blender/collada/GeometryExporter.h
@@ -39,8 +39,6 @@
#include "BlenderContext.h"
#include "BKE_key.h"
-struct Depsgraph;
-
class Normal {
public:
float x;
@@ -58,8 +56,6 @@ class GeometryExporter : COLLADASW::LibraryGeometries {
unsigned int v1, v2, v3, v4;
};
- Normal n;
-
public:
/* TODO: optimize UV sets by making indexed list with duplicates removed */
GeometryExporter(BlenderContext &blender_context,
diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h
index df6e72cbf3a..72753e170a3 100644
--- a/source/blender/collada/collada.h
+++ b/source/blender/collada/collada.h
@@ -34,9 +34,6 @@ extern "C" {
#include "BLI_path_util.h"
#include "RNA_types.h"
-struct Depsgraph;
-struct Scene;
-struct ViewLayer;
struct bContext;
/*
diff --git a/source/blender/collada/collada_utils.h b/source/blender/collada/collada_utils.h
index c23e33df76d..c0425e59d1a 100644
--- a/source/blender/collada/collada_utils.h
+++ b/source/blender/collada/collada_utils.h
@@ -69,8 +69,6 @@ extern "C" {
constexpr int LIMITTED_PRECISION = 6;
-struct Depsgraph;
-
typedef std::map<COLLADAFW::UniqueId, Image *> UidImageMap;
typedef std::map<std::string, Image *> KeyImageMap;
typedef std::map<COLLADAFW::TextureMapId, std::vector<MTex *>> TexIndexTextureArrayMap;
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt
index 50b5951f99f..2a8914c8cd9 100644
--- a/source/blender/compositor/CMakeLists.txt
+++ b/source/blender/compositor/CMakeLists.txt
@@ -280,8 +280,8 @@ set(SRC
nodes/COM_BlurNode.h
nodes/COM_BokehBlurNode.cpp
nodes/COM_BokehBlurNode.h
- nodes/COM_DenoiseNode.h
nodes/COM_DenoiseNode.cpp
+ nodes/COM_DenoiseNode.h
nodes/COM_DespeckleNode.cpp
nodes/COM_DespeckleNode.h
nodes/COM_DilateErodeNode.cpp
@@ -491,8 +491,8 @@ set(SRC
operations/COM_ConvolutionEdgeFilterOperation.h
operations/COM_ConvolutionFilterOperation.cpp
operations/COM_ConvolutionFilterOperation.h
- operations/COM_DenoiseOperation.h
operations/COM_DenoiseOperation.cpp
+ operations/COM_DenoiseOperation.h
operations/COM_DespeckleOperation.cpp
operations/COM_DespeckleOperation.h
operations/COM_DilateErodeOperation.cpp
diff --git a/source/blender/compositor/intern/COM_CompositorContext.h b/source/blender/compositor/intern/COM_CompositorContext.h
index f4cd60e3ee0..b28d5ff0cdf 100644
--- a/source/blender/compositor/intern/COM_CompositorContext.h
+++ b/source/blender/compositor/intern/COM_CompositorContext.h
@@ -215,7 +215,7 @@ class CompositorContext {
}
/**
- * \brief get the current framenumber of the scene in this context
+ * \brief get the current frame-number of the scene in this context
*/
int getFramenumber() const;
diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h
index df936818f33..7e5b0264aa3 100644
--- a/source/blender/compositor/intern/COM_MemoryBuffer.h
+++ b/source/blender/compositor/intern/COM_MemoryBuffer.h
@@ -73,7 +73,7 @@ class MemoryBuffer {
rcti m_rect;
/**
- * brief refers to the chunknumber within the executiongroup where related to the MemoryProxy
+ * brief refers to the chunk-number within the execution-group where related to the MemoryProxy
* \see memoryProxy
*/
unsigned int m_chunkNumber;
diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h
index af9ed2648c9..6b073452771 100644
--- a/source/blender/compositor/intern/COM_NodeOperation.h
+++ b/source/blender/compositor/intern/COM_NodeOperation.h
@@ -368,7 +368,7 @@ class NodeOperation : public SocketReader {
return true;
}
- inline bool isBreaked() const
+ inline bool isBraked() const
{
return this->m_btree->test_break(this->m_btree->tbh);
}
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.cpp b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
index 0aa054b8c77..2529637801d 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.cpp
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.cpp
@@ -248,7 +248,7 @@ void OpenCLDevice::COM_clEnqueueRange(cl_kernel kernel,
printf("CLERROR[%d]: %s\n", error, clewErrorString(error));
}
clFlush(this->m_queue);
- if (operation->isBreaked()) {
+ if (operation->isBraked()) {
breaked = false;
}
}
diff --git a/source/blender/compositor/intern/COM_OpenCLDevice.h b/source/blender/compositor/intern/COM_OpenCLDevice.h
index 7a83bda162c..45ce77acac7 100644
--- a/source/blender/compositor/intern/COM_OpenCLDevice.h
+++ b/source/blender/compositor/intern/COM_OpenCLDevice.h
@@ -78,8 +78,8 @@ class OpenCLDevice : public Device {
bool initialize();
/**
- * \brief deinitialize the device
- * During deintiialization the command queue is cleared
+ * \brief de-initialize the device
+ * During de-initialization the command queue is cleared
*/
void deinitialize();
diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp
index dc3f65deb1f..6bce56ffd52 100644
--- a/source/blender/compositor/nodes/COM_ImageNode.cpp
+++ b/source/blender/compositor/nodes/COM_ImageNode.cpp
@@ -195,7 +195,7 @@ void ImageNode::convertToOperations(NodeConverter &converter,
}
}
- /* incase we can't load the layer */
+ /* In case we can't load the layer. */
if (operation == NULL) {
converter.setInvalidOutput(getOutputSocket(index));
}
diff --git a/source/blender/compositor/nodes/COM_MathNode.cpp b/source/blender/compositor/nodes/COM_MathNode.cpp
index 5a2f934f37f..d13b34bb6b5 100644
--- a/source/blender/compositor/nodes/COM_MathNode.cpp
+++ b/source/blender/compositor/nodes/COM_MathNode.cpp
@@ -29,61 +29,61 @@ void MathNode::convertToOperations(NodeConverter &converter,
case NODE_MATH_ADD:
operation = new MathAddOperation();
break;
- case NODE_MATH_SUB:
+ case NODE_MATH_SUBTRACT:
operation = new MathSubtractOperation();
break;
- case NODE_MATH_MUL:
+ case NODE_MATH_MULTIPLY:
operation = new MathMultiplyOperation();
break;
case NODE_MATH_DIVIDE:
operation = new MathDivideOperation();
break;
- case NODE_MATH_SIN:
+ case NODE_MATH_SINE:
operation = new MathSineOperation();
break;
- case NODE_MATH_COS:
+ case NODE_MATH_COSINE:
operation = new MathCosineOperation();
break;
- case NODE_MATH_TAN:
+ case NODE_MATH_TANGENT:
operation = new MathTangentOperation();
break;
- case NODE_MATH_ASIN:
+ case NODE_MATH_ARCSINE:
operation = new MathArcSineOperation();
break;
- case NODE_MATH_ACOS:
+ case NODE_MATH_ARCCOSINE:
operation = new MathArcCosineOperation();
break;
- case NODE_MATH_ATAN:
+ case NODE_MATH_ARCTANGENT:
operation = new MathArcTangentOperation();
break;
- case NODE_MATH_POW:
+ case NODE_MATH_POWER:
operation = new MathPowerOperation();
break;
- case NODE_MATH_LOG:
+ case NODE_MATH_LOGARITHM:
operation = new MathLogarithmOperation();
break;
- case NODE_MATH_MIN:
+ case NODE_MATH_MINIMUM:
operation = new MathMinimumOperation();
break;
- case NODE_MATH_MAX:
+ case NODE_MATH_MAXIMUM:
operation = new MathMaximumOperation();
break;
case NODE_MATH_ROUND:
operation = new MathRoundOperation();
break;
- case NODE_MATH_LESS:
+ case NODE_MATH_LESS_THAN:
operation = new MathLessThanOperation();
break;
- case NODE_MATH_GREATER:
+ case NODE_MATH_GREATER_THAN:
operation = new MathGreaterThanOperation();
break;
- case NODE_MATH_MOD:
+ case NODE_MATH_MODULO:
operation = new MathModuloOperation();
break;
- case NODE_MATH_ABS:
+ case NODE_MATH_ABSOLUTE:
operation = new MathAbsoluteOperation();
break;
- case NODE_MATH_ATAN2:
+ case NODE_MATH_ARCTAN2:
operation = new MathArcTan2Operation();
break;
case NODE_MATH_FLOOR:
@@ -92,7 +92,7 @@ void MathNode::convertToOperations(NodeConverter &converter,
case NODE_MATH_CEIL:
operation = new MathCeilOperation();
break;
- case NODE_MATH_FRACT:
+ case NODE_MATH_FRACTION:
operation = new MathFractOperation();
break;
case NODE_MATH_SQRT:
diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp
index 27a605e28d4..b3bcefaccb5 100644
--- a/source/blender/compositor/nodes/COM_MixNode.cpp
+++ b/source/blender/compositor/nodes/COM_MixNode.cpp
@@ -52,7 +52,7 @@ void MixNode::convertToOperations(NodeConverter &converter,
convertProg = new MixLightenOperation();
break;
case MA_RAMP_BURN:
- convertProg = new MixBurnOperation();
+ convertProg = new MixColorBurnOperation();
break;
case MA_RAMP_HUE:
convertProg = new MixHueOperation();
diff --git a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp
index 68b5af3089a..1578a805d1e 100644
--- a/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp
+++ b/source/blender/compositor/operations/COM_ColorBalanceLGGOperation.cpp
@@ -22,7 +22,7 @@
inline float colorbalance_lgg(float in, float lift_lgg, float gamma_inv, float gain)
{
/* 1:1 match with the sequencer with linear/srgb conversions, the conversion isnt pretty
- * but best keep it this way, sice testing for durian shows a similar calculation
+ * but best keep it this way, since testing for durian shows a similar calculation
* without lin/srgb conversions gives bad results (over-saturated shadows) with colors
* slightly below 1.0. some correction can be done but it ends up looking bad for shadows or
* lighter tones - campbell */
diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp
index 40315d217ce..5bd466658c0 100644
--- a/source/blender/compositor/operations/COM_CompositorOperation.cpp
+++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp
@@ -78,7 +78,7 @@ void CompositorOperation::deinitExecution()
return;
}
- if (!isBreaked()) {
+ if (!isBraked()) {
Render *re = RE_GetSceneRender(this->m_scene);
RenderResult *rr = RE_AcquireResultWrite(re);
@@ -207,7 +207,7 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
zbuffer[offset] = color[0];
offset4 += COM_NUM_CHANNELS_COLOR;
offset++;
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
}
diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.cpp b/source/blender/compositor/operations/COM_DenoiseOperation.cpp
index af568490c72..3aeaba539f9 100644
--- a/source/blender/compositor/operations/COM_DenoiseOperation.cpp
+++ b/source/blender/compositor/operations/COM_DenoiseOperation.cpp
@@ -21,16 +21,19 @@
#include "COM_DenoiseOperation.h"
#include "BLI_math.h"
+#include "BLI_system.h"
#ifdef WITH_OPENIMAGEDENOISE
+# include "BLI_threads.h"
# include <OpenImageDenoise/oidn.hpp>
+static pthread_mutex_t oidn_lock = BLI_MUTEX_INITIALIZER;
#endif
#include <iostream>
DenoiseOperation::DenoiseOperation() : SingleThreadedOperation()
{
this->addInputSocket(COM_DT_COLOR);
- this->addInputSocket(COM_DT_COLOR);
this->addInputSocket(COM_DT_VECTOR);
+ this->addInputSocket(COM_DT_COLOR);
this->addOutputSocket(COM_DT_COLOR);
this->m_settings = NULL;
}
@@ -38,23 +41,23 @@ void DenoiseOperation::initExecution()
{
SingleThreadedOperation::initExecution();
this->m_inputProgramColor = getInputSocketReader(0);
- this->m_inputProgramAlbedo = getInputSocketReader(1);
- this->m_inputProgramNormal = getInputSocketReader(2);
+ this->m_inputProgramNormal = getInputSocketReader(1);
+ this->m_inputProgramAlbedo = getInputSocketReader(2);
}
void DenoiseOperation::deinitExecution()
{
this->m_inputProgramColor = NULL;
- this->m_inputProgramAlbedo = NULL;
this->m_inputProgramNormal = NULL;
+ this->m_inputProgramAlbedo = NULL;
SingleThreadedOperation::deinitExecution();
}
MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2)
{
MemoryBuffer *tileColor = (MemoryBuffer *)this->m_inputProgramColor->initializeTileData(rect2);
- MemoryBuffer *tileAlbedo = (MemoryBuffer *)this->m_inputProgramAlbedo->initializeTileData(rect2);
MemoryBuffer *tileNormal = (MemoryBuffer *)this->m_inputProgramNormal->initializeTileData(rect2);
+ MemoryBuffer *tileAlbedo = (MemoryBuffer *)this->m_inputProgramAlbedo->initializeTileData(rect2);
rcti rect;
rect.xmin = 0;
rect.ymin = 0;
@@ -62,7 +65,7 @@ MemoryBuffer *DenoiseOperation::createMemoryBuffer(rcti *rect2)
rect.ymax = getHeight();
MemoryBuffer *result = new MemoryBuffer(COM_DT_COLOR, &rect);
float *data = result->getBuffer();
- this->generateDenoise(data, tileColor, tileAlbedo, tileNormal, this->m_settings);
+ this->generateDenoise(data, tileColor, tileNormal, tileAlbedo, this->m_settings);
return result;
}
@@ -85,8 +88,8 @@ bool DenoiseOperation::determineDependingAreaOfInterest(rcti * /*input*/,
void DenoiseOperation::generateDenoise(float *data,
MemoryBuffer *inputTileColor,
- MemoryBuffer *inputTileAlbedo,
MemoryBuffer *inputTileNormal,
+ MemoryBuffer *inputTileAlbedo,
NodeDenoise *settings)
{
float *inputBufferColor = inputTileColor->getBuffer();
@@ -95,60 +98,69 @@ void DenoiseOperation::generateDenoise(float *data,
return;
}
#ifdef WITH_OPENIMAGEDENOISE
- oidn::DeviceRef device = oidn::newDevice();
- device.commit();
+ if (BLI_cpu_support_sse41()) {
+ oidn::DeviceRef device = oidn::newDevice();
+ device.commit();
- oidn::FilterRef filter = device.newFilter("RT");
- filter.setImage("color",
- inputBufferColor,
- oidn::Format::Float3,
- inputTileColor->getWidth(),
- inputTileColor->getHeight(),
- 0,
- 4 * sizeof(float));
- if (inputTileAlbedo && inputTileAlbedo->getBuffer()) {
- filter.setImage("albedo",
- inputTileAlbedo->getBuffer(),
+ oidn::FilterRef filter = device.newFilter("RT");
+ filter.setImage("color",
+ inputBufferColor,
oidn::Format::Float3,
- inputTileAlbedo->getWidth(),
- inputTileAlbedo->getHeight(),
+ inputTileColor->getWidth(),
+ inputTileColor->getHeight(),
0,
4 * sizeof(float));
- }
- if (inputTileNormal && inputTileNormal->getBuffer()) {
- filter.setImage("normal",
- inputTileNormal->getBuffer(),
+ if (inputTileNormal && inputTileNormal->getBuffer()) {
+ filter.setImage("normal",
+ inputTileNormal->getBuffer(),
+ oidn::Format::Float3,
+ inputTileNormal->getWidth(),
+ inputTileNormal->getHeight(),
+ 0,
+ 3 * sizeof(float));
+ }
+ if (inputTileAlbedo && inputTileAlbedo->getBuffer()) {
+ filter.setImage("albedo",
+ inputTileAlbedo->getBuffer(),
+ oidn::Format::Float3,
+ inputTileAlbedo->getWidth(),
+ inputTileAlbedo->getHeight(),
+ 0,
+ 4 * sizeof(float));
+ }
+ filter.setImage("output",
+ data,
oidn::Format::Float3,
- inputTileNormal->getWidth(),
- inputTileNormal->getHeight(),
+ inputTileColor->getWidth(),
+ inputTileColor->getHeight(),
0,
- 3 * sizeof(float));
- }
- filter.setImage("output",
- data,
- oidn::Format::Float3,
- inputTileColor->getWidth(),
- inputTileColor->getHeight(),
- 0,
- 4 * sizeof(float));
+ 4 * sizeof(float));
- BLI_assert(settings);
- if (settings) {
- filter.set("hdr", settings->hdr);
- filter.set("srgb", false);
- }
+ BLI_assert(settings);
+ if (settings) {
+ filter.set("hdr", settings->hdr);
+ filter.set("srgb", false);
+ }
- filter.commit();
- filter.execute();
+ filter.commit();
+ /* Since it's memory intensive, it's better to run only one instance of OIDN at a time.
+ * OpenImageDenoise is multithreaded internally and should use all available cores nonetheless.
+ */
+ BLI_mutex_lock(&oidn_lock);
+ filter.execute();
+ BLI_mutex_unlock(&oidn_lock);
- /* copy the alpha channel, OpenImageDenoise currently only supports RGB */
- size_t numPixels = inputTileColor->getWidth() * inputTileColor->getHeight();
- for (size_t i = 0; i < numPixels; ++i) {
- data[i * 4 + 3] = inputBufferColor[i * 4 + 3];
+ /* copy the alpha channel, OpenImageDenoise currently only supports RGB */
+ size_t numPixels = inputTileColor->getWidth() * inputTileColor->getHeight();
+ for (size_t i = 0; i < numPixels; ++i) {
+ data[i * 4 + 3] = inputBufferColor[i * 4 + 3];
+ }
+ return;
}
-#else
+#endif
+ /* If built without OIDN or running on an unsupported CPU, just pass through. */
+ UNUSED_VARS(inputTileAlbedo, inputTileNormal, settings);
::memcpy(data,
inputBufferColor,
inputTileColor->getWidth() * inputTileColor->getHeight() * sizeof(float) * 4);
-#endif
}
diff --git a/source/blender/compositor/operations/COM_DenoiseOperation.h b/source/blender/compositor/operations/COM_DenoiseOperation.h
index 6e19bd6034a..73165174932 100644
--- a/source/blender/compositor/operations/COM_DenoiseOperation.h
+++ b/source/blender/compositor/operations/COM_DenoiseOperation.h
@@ -62,8 +62,8 @@ class DenoiseOperation : public SingleThreadedOperation {
protected:
void generateDenoise(float *data,
MemoryBuffer *inputTileColor,
- MemoryBuffer *inputTileAlbedo,
MemoryBuffer *inputTileNormal,
+ MemoryBuffer *inputTileAlbedo,
NodeDenoise *settings);
MemoryBuffer *createMemoryBuffer(rcti *rect);
diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp
index 944a1d9c5dc..9f01cf5d63a 100644
--- a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp
@@ -51,7 +51,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
if (!breaked) {
FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 1, 3);
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
if (!breaked) {
@@ -60,19 +60,19 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
MemoryBuffer *tbuf2 = tbuf1->duplicate();
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
if (!breaked) {
FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 0, 3);
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
if (!breaked) {
FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 1, 3);
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
if (!breaked) {
@@ -117,7 +117,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
gbuf->writePixel(x, y, c);
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
}
@@ -142,7 +142,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No
}
tbuf1->addPixel(x, y, tc);
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
}
diff --git a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp
index 1ceeba18960..75c2ae51bde 100644
--- a/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareSimpleStarOperation.cpp
@@ -58,7 +58,7 @@ void GlareSimpleStarOperation::generateGlare(float *data,
c[3] = 1.0f;
tbuf2->writePixel(x, y, c);
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
}
@@ -87,7 +87,7 @@ void GlareSimpleStarOperation::generateGlare(float *data,
c[3] = 1.0f;
tbuf2->writePixel(x, y, c);
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
}
diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
index 78ca373faaf..951dec9281e 100644
--- a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
+++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp
@@ -78,7 +78,7 @@ void GlareStreaksOperation::generateGlare(float *data,
tdstcol[2] = 0.5f * (tdstcol[2] + c1[2] + wt * (c2[2] + wt * (c3[2] + wt * c4[2])));
tdstcol[3] = 1.0f;
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
}
diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp
index 0c9208fb6bb..88a3a5c535c 100644
--- a/source/blender/compositor/operations/COM_MaskOperation.cpp
+++ b/source/blender/compositor/operations/COM_MaskOperation.cpp
@@ -148,7 +148,7 @@ void MaskOperation::executePixelSampled(float output[4],
}
}
else {
- /* incase loop below fails */
+ /* In case loop below fails. */
output[0] = 0.0f;
for (unsigned int i = 0; i < this->m_rasterMaskHandleTot; i++) {
diff --git a/source/blender/compositor/operations/COM_MixOperation.cpp b/source/blender/compositor/operations/COM_MixOperation.cpp
index a610cb0d1e8..6b8a0caa13b 100644
--- a/source/blender/compositor/operations/COM_MixOperation.cpp
+++ b/source/blender/compositor/operations/COM_MixOperation.cpp
@@ -162,12 +162,15 @@ void MixBlendOperation::executePixelSampled(float output[4],
/* ******** Mix Burn Operation ******** */
-MixBurnOperation::MixBurnOperation() : MixBaseOperation()
+MixColorBurnOperation::MixColorBurnOperation() : MixBaseOperation()
{
/* pass */
}
-void MixBurnOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
+void MixColorBurnOperation::executePixelSampled(float output[4],
+ float x,
+ float y,
+ PixelSampler sampler)
{
float inputColor1[4];
float inputColor2[4];
diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h
index 6ea55a3edfd..fbf60fb9d37 100644
--- a/source/blender/compositor/operations/COM_MixOperation.h
+++ b/source/blender/compositor/operations/COM_MixOperation.h
@@ -95,9 +95,9 @@ class MixBlendOperation : public MixBaseOperation {
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
-class MixBurnOperation : public MixBaseOperation {
+class MixColorBurnOperation : public MixBaseOperation {
public:
- MixBurnOperation();
+ MixColorBurnOperation();
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
};
diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp
index d5b9edae719..3f7619523e3 100644
--- a/source/blender/compositor/operations/COM_ViewerOperation.cpp
+++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp
@@ -111,7 +111,7 @@ void ViewerOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/)
offset++;
offset4 += 4;
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
offset += offsetadd;
diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
index beba29e6755..6c5e45472a8 100644
--- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
+++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp
@@ -76,7 +76,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/
this->m_input->read(&(buffer[offset4]), x, y, data);
offset4 += num_channels;
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
}
@@ -100,7 +100,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int /*tileNumber*/
this->m_input->readSampled(&(buffer[offset4]), x, y, COM_PS_NEAREST);
offset4 += num_channels;
}
- if (isBreaked()) {
+ if (isBraked()) {
breaked = true;
}
}
@@ -119,7 +119,7 @@ void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice *device,
/*
* 1. create cl_mem from outputbuffer
* 2. call NodeOperation (input) executeOpenCLChunk(.....)
- * 3. schedule readback from opencl to main device (outputbuffer)
+ * 3. schedule read back from opencl to main device (outputbuffer)
* 4. schedule native callback
*
* note: list of cl_mem will be filled by 2, and needs to be cleaned up by 4
diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h
index bdcb4061096..7553eca9b64 100644
--- a/source/blender/depsgraph/DEG_depsgraph.h
+++ b/source/blender/depsgraph/DEG_depsgraph.h
@@ -55,9 +55,6 @@ typedef struct Depsgraph Depsgraph;
struct Main;
-struct PointerRNA;
-struct PropertyRNA;
-struct RenderEngineType;
struct Scene;
struct ViewLayer;
@@ -111,6 +108,8 @@ void DEG_graph_on_visible_update(struct Main *bmain, Depsgraph *depsgraph, const
/* Update all dependency graphs when visible scenes/layers changes. */
void DEG_on_visible_update(struct Main *bmain, const bool do_time);
+/* NOTE: Will return NULL if the flag is not known, allowing to gracefully handle situations
+ * when recalc flag has been removed. */
const char *DEG_update_tag_as_string(IDRecalcFlag flag);
void DEG_id_tag_update(struct ID *id, int flag);
diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h
index 18e06410adf..37dfaf2c3e2 100644
--- a/source/blender/depsgraph/DEG_depsgraph_build.h
+++ b/source/blender/depsgraph/DEG_depsgraph_build.h
@@ -34,12 +34,9 @@ struct Depsgraph;
/* ------------------------------------------------ */
struct CacheFile;
-struct Collection;
struct CustomData_MeshMasks;
-struct EffectorWeights;
struct ID;
struct Main;
-struct ModifierData;
struct Object;
struct Scene;
struct ViewLayer;
diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h
index e3381e79e9c..82f7f33411a 100644
--- a/source/blender/depsgraph/DEG_depsgraph_query.h
+++ b/source/blender/depsgraph/DEG_depsgraph_query.h
@@ -32,14 +32,13 @@
/* Needed for the instance iterator. */
#include "DNA_object_types.h"
-struct ID;
-
struct BLI_Iterator;
-struct Base;
struct CustomData_MeshMasks;
struct Depsgraph;
struct DupliObject;
+struct ID;
struct ListBase;
+struct PointerRNA;
struct Scene;
struct ViewLayer;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc
index 3df707e92c1..3cfb4f95e5e 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc
@@ -103,9 +103,9 @@ void animated_property_cb(ID * /*id*/, FCurve *fcurve, void *data_v)
/* Get storage for the ID.
* This is needed to deal with cases when nested datablock is animated by its parent. */
AnimatedPropertyStorage *animated_property_storage = data->animated_property_storage;
- if (pointer_rna.id.data != data->pointer_rna.id.data) {
+ if (pointer_rna.owner_id != data->pointer_rna.owner_id) {
animated_property_storage = data->builder_cache->ensureAnimatedPropertyStorage(
- reinterpret_cast<ID *>(pointer_rna.id.data));
+ pointer_rna.owner_id);
}
/* Set the property as animated. */
animated_property_storage->tagPropertyAsAnimated(&pointer_rna, property_rna);
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
index d11a60b77dd..bfb1a981c4d 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_cycle.cc
@@ -149,7 +149,7 @@ bool check_relation_can_murder(Relation *relation)
Relation *select_relation_to_murder(Relation *relation, StackEntry *cycle_start_entry)
{
- /* More or less russian roulette solver, which will make sure only
+ /* More or less Russian roulette solver, which will make sure only
* specially marked relations are kept alive.
*
* TODO(sergey): There might be better strategies here. */
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_map.h b/source/blender/depsgraph/intern/builder/deg_builder_map.h
index 0767837a587..65b493e2467 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_map.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_map.h
@@ -25,7 +25,6 @@
#include "intern/depsgraph_type.h"
-struct GSet;
struct ID;
namespace DEG {
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
index de9f0e4d6cd..65f3521b556 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h
@@ -31,7 +31,6 @@
#include "DEG_depsgraph.h"
-struct Base;
struct CacheFile;
struct Camera;
struct Collection;
@@ -44,14 +43,12 @@ struct LayerCollection;
struct Light;
struct LightProbe;
struct ListBase;
-struct MTex;
struct Main;
struct Mask;
struct Material;
struct MovieClip;
struct Object;
struct ParticleSettings;
-struct Probe;
struct Scene;
struct Speaker;
struct Tex;
@@ -64,15 +61,12 @@ struct bNodeTree;
struct bPoseChannel;
struct bSound;
-struct PropertyRNA;
-
namespace DEG {
struct ComponentNode;
struct Depsgraph;
class DepsgraphBuilderCache;
struct IDNode;
-struct Node;
struct OperationNode;
struct TimeSourceNode;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index 3c226338bfd..c7b545e9feb 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -807,13 +807,25 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object)
{
Object *parent = object->parent;
ID *parent_id = &object->parent->id;
- ComponentKey ob_key(&object->id, NodeType::TRANSFORM);
- /* Type-specific links/ */
+ ComponentKey object_transform_key(&object->id, NodeType::TRANSFORM);
+ /* Type-specific links. */
switch (object->partype) {
/* Armature Deform (Virtual Modifier) */
case PARSKEL: {
- ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- add_relation(parent_key, ob_key, "Armature Deform Parent");
+ ComponentKey parent_transform_key(parent_id, NodeType::TRANSFORM);
+ add_relation(parent_transform_key, object_transform_key, "Parent Armature Transform");
+
+ if (parent->type == OB_ARMATURE) {
+ ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY);
+ ComponentKey parent_pose_key(parent_id, NodeType::EVAL_POSE);
+ add_relation(
+ parent_transform_key, object_geometry_key, "Parent Armature Transform -> Geometry");
+ add_relation(parent_pose_key, object_geometry_key, "Parent Armature Pose -> Geometry");
+
+ add_depends_on_transform_relation(
+ &object->id, object_geometry_key, "Virtual Armature Modifier");
+ }
+
break;
}
@@ -821,7 +833,7 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object)
case PARVERT1:
case PARVERT3: {
ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
- add_relation(parent_key, ob_key, "Vertex Parent");
+ add_relation(parent_key, object_transform_key, "Vertex Parent");
/* Original index is used for optimizations of lookups for subdiv
* only meshes.
* TODO(sergey): This optimization got lost at 2.8, so either verify
@@ -833,7 +845,7 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object)
DEGCustomDataMeshMasks::MaskFace(CD_MASK_ORIGINDEX) |
DEGCustomDataMeshMasks::MaskPoly(CD_MASK_ORIGINDEX));
ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
- add_relation(transform_key, ob_key, "Vertex Parent TFM");
+ add_relation(transform_key, object_transform_key, "Vertex Parent TFM");
break;
}
@@ -842,8 +854,8 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object)
ComponentKey parent_bone_key(parent_id, NodeType::BONE, object->parsubstr);
OperationKey parent_transform_key(
parent_id, NodeType::TRANSFORM, OperationCode::TRANSFORM_FINAL);
- add_relation(parent_bone_key, ob_key, "Bone Parent");
- add_relation(parent_transform_key, ob_key, "Armature Parent");
+ add_relation(parent_bone_key, object_transform_key, "Bone Parent");
+ add_relation(parent_transform_key, object_transform_key, "Armature Parent");
break;
}
@@ -852,8 +864,8 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object)
/* Lattice Deform Parent - Virtual Modifier. */
ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
ComponentKey geom_key(parent_id, NodeType::GEOMETRY);
- add_relation(parent_key, ob_key, "Lattice Deform Parent");
- add_relation(geom_key, ob_key, "Lattice Deform Parent Geom");
+ add_relation(parent_key, object_transform_key, "Lattice Deform Parent");
+ add_relation(geom_key, object_transform_key, "Lattice Deform Parent Geom");
}
else if (object->parent->type == OB_CURVE) {
Curve *cu = (Curve *)object->parent->data;
@@ -861,20 +873,20 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object)
if (cu->flag & CU_PATH) {
/* Follow Path. */
ComponentKey parent_key(parent_id, NodeType::GEOMETRY);
- add_relation(parent_key, ob_key, "Curve Follow Parent");
+ add_relation(parent_key, object_transform_key, "Curve Follow Parent");
ComponentKey transform_key(parent_id, NodeType::TRANSFORM);
- add_relation(transform_key, ob_key, "Curve Follow TFM");
+ add_relation(transform_key, object_transform_key, "Curve Follow TFM");
}
else {
/* Standard Parent. */
ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- add_relation(parent_key, ob_key, "Curve Parent");
+ add_relation(parent_key, object_transform_key, "Curve Parent");
}
}
else {
/* Standard Parent. */
ComponentKey parent_key(parent_id, NodeType::TRANSFORM);
- add_relation(parent_key, ob_key, "Parent");
+ add_relation(parent_key, object_transform_key, "Parent");
}
break;
}
@@ -887,7 +899,7 @@ void DepsgraphRelationBuilder::build_object_parent(Object *object)
ComponentKey parent_geometry_key(parent_id, NodeType::GEOMETRY);
/* NOTE: Metaballs are evaluating geometry only after their transform,
* so we only hook up to transform channel here. */
- add_relation(parent_geometry_key, ob_key, "Parent");
+ add_relation(parent_geometry_key, object_transform_key, "Parent");
}
/* Dupliverts uses original vertex index. */
@@ -1384,7 +1396,7 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
* it. This is necessary to provide more granular dependencies specifically for
* Bone objects, because the armature data doesn't have per-bone components,
* and generic add_relation can only add one link. */
- ID *id_ptr = (ID *)property_entry_key.ptr.id.data;
+ ID *id_ptr = property_entry_key.ptr.owner_id;
bool is_bone = id_ptr && property_entry_key.ptr.type == &RNA_Bone;
/* If the Bone property is referenced via obj.pose.bones[].bone,
* the RNA pointer refers to the Object ID, so skip to data. */
@@ -1433,8 +1445,8 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
PointerRNA ptr;
RNA_id_pointer_create(id, &id_ptr);
if (RNA_path_resolve_full(&id_ptr, fcu->rna_path, &ptr, NULL, NULL)) {
- if (id_ptr.id.data != ptr.id.data) {
- ComponentKey cow_key((ID *)ptr.id.data, NodeType::COPY_ON_WRITE);
+ if (id_ptr.owner_id != ptr.owner_id) {
+ ComponentKey cow_key(ptr.owner_id, NodeType::COPY_ON_WRITE);
add_relation(cow_key, driver_key, "Driven CoW -> Driver", RELATION_CHECK_BEFORE_ADD);
}
}
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
index 0e15818622f..e58ef989ac9 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h
@@ -51,7 +51,6 @@ struct Camera;
struct Collection;
struct EffectorWeights;
struct FCurve;
-struct GHash;
struct ID;
struct Image;
struct Key;
@@ -59,11 +58,9 @@ struct LayerCollection;
struct Light;
struct LightProbe;
struct ListBase;
-struct MTex;
struct Main;
struct Mask;
struct Material;
-struct ModifierData;
struct MovieClip;
struct Object;
struct ParticleSettings;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
index be494104522..d3ae3da9b56 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc
@@ -177,7 +177,7 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
return node_identifier;
}
/* Set default values for returns. */
- node_identifier.id = static_cast<ID *>(ptr->id.data);
+ node_identifier.id = ptr->owner_id;
node_identifier.component_name = "";
node_identifier.operation_code = OperationCode::OPERATION;
node_identifier.operation_name = "";
@@ -239,7 +239,7 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
return node_identifier;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
- const Object *object = static_cast<const Object *>(ptr->id.data);
+ const Object *object = reinterpret_cast<const Object *>(ptr->owner_id);
const bConstraint *constraint = static_cast<const bConstraint *>(ptr->data);
RNANodeQueryIDData *id_data = ensure_id_data(&object->id);
/* Check whether is object or bone constraint. */
@@ -259,7 +259,7 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
return node_identifier;
}
else if (ELEM(ptr->type, &RNA_ConstraintTarget, &RNA_ConstraintTargetBone)) {
- Object *object = (Object *)ptr->id.data;
+ Object *object = reinterpret_cast<Object *>(ptr->owner_id);
bConstraintTarget *tgt = (bConstraintTarget *)ptr->data;
/* Check whether is object or bone constraint. */
bPoseChannel *pchan = NULL;
@@ -323,14 +323,14 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
}
else if (ptr->type == &RNA_ShapeKey) {
KeyBlock *key_block = static_cast<KeyBlock *>(ptr->data);
- node_identifier.id = static_cast<ID *>(ptr->id.data);
+ node_identifier.id = ptr->owner_id;
node_identifier.type = NodeType::PARAMETERS;
node_identifier.operation_code = OperationCode::PARAMETERS_EVAL;
node_identifier.operation_name = key_block->name;
return node_identifier;
}
else if (ptr->type == &RNA_Key) {
- node_identifier.id = static_cast<ID *>(ptr->id.data);
+ node_identifier.id = ptr->owner_id;
node_identifier.type = NodeType::GEOMETRY;
return node_identifier;
}
@@ -348,12 +348,12 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr,
return node_identifier;
}
else if (ELEM(ptr->type, &RNA_Curve, &RNA_TextCurve)) {
- node_identifier.id = (ID *)ptr->id.data;
+ node_identifier.id = ptr->owner_id;
node_identifier.type = NodeType::GEOMETRY;
return node_identifier;
}
else if (ELEM(ptr->type, &RNA_BezierSplinePoint, &RNA_SplinePoint)) {
- node_identifier.id = (ID *)ptr->id.data;
+ node_identifier.id = ptr->owner_id;
node_identifier.type = NodeType::GEOMETRY;
return node_identifier;
}
diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h
index 15ce57cb169..96b1a2a1f8a 100644
--- a/source/blender/depsgraph/intern/depsgraph.h
+++ b/source/blender/depsgraph/intern/depsgraph.h
@@ -45,13 +45,11 @@
struct GHash;
struct GSet;
struct ID;
-struct Main;
struct Scene;
struct ViewLayer;
namespace DEG {
-struct ComponentNode;
struct IDNode;
struct Node;
struct OperationNode;
diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc
index 23f2bf4194f..8556a351e2b 100644
--- a/source/blender/depsgraph/intern/depsgraph_query.cc
+++ b/source/blender/depsgraph/intern/depsgraph_query.cc
@@ -205,11 +205,11 @@ void DEG_get_evaluated_rna_pointer(const Depsgraph *depsgraph,
if ((ptr == NULL) || (r_ptr_eval == NULL)) {
return;
}
- ID *orig_id = (ID *)ptr->id.data;
+ ID *orig_id = ptr->owner_id;
ID *cow_id = DEG_get_evaluated_id(depsgraph, orig_id);
- if (ptr->id.data == ptr->data) {
+ if (ptr->owner_id == ptr->data) {
/* For ID pointers, it's easy... */
- r_ptr_eval->id.data = (void *)cow_id;
+ r_ptr_eval->owner_id = cow_id;
r_ptr_eval->data = (void *)cow_id;
r_ptr_eval->type = ptr->type;
}
@@ -220,7 +220,7 @@ void DEG_get_evaluated_rna_pointer(const Depsgraph *depsgraph,
const Object *ob_eval = (Object *)cow_id;
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
const bPoseChannel *pchan_eval = BKE_pose_channel_find_name(ob_eval->pose, pchan->name);
- r_ptr_eval->id.data = (void *)cow_id;
+ r_ptr_eval->owner_id = cow_id;
r_ptr_eval->data = (void *)pchan_eval;
r_ptr_eval->type = ptr->type;
}
diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc
index 392514990e3..72ef495f1d5 100644
--- a/source/blender/depsgraph/intern/depsgraph_tag.cc
+++ b/source/blender/depsgraph/intern/depsgraph_tag.cc
@@ -412,11 +412,15 @@ static void graph_id_tag_update_single_flag(Main *bmain,
string stringify_append_bit(const string &str, IDRecalcFlag tag)
{
+ const char *tag_name = DEG_update_tag_as_string(tag);
+ if (tag_name == NULL) {
+ return str;
+ }
string result = str;
if (!result.empty()) {
result += ", ";
}
- result += DEG_update_tag_as_string(tag);
+ result += tag_name;
return result;
}
@@ -638,7 +642,7 @@ void graph_id_tag_update(
* This way IDs in the undo steps will have this flag preserved, making it possible to restore
* all needed tags when new dependency graph is created on redo.
* This is the only way to ensure modifications to animation data (such as keyframes i.e.)
- * properly triggers animation update for the newely constructed dependency graph on redo (while
+ * properly triggers animation update for the newly constructed dependency graph on redo (while
* usually newly created dependency graph skips animation update to avoid loss of unkeyed
* changes). */
if (update_source == DEG_UPDATE_SOURCE_USER_EDIT) {
@@ -717,8 +721,7 @@ const char *DEG_update_tag_as_string(IDRecalcFlag flag)
case ID_RECALC_ALL:
return "ALL";
}
- BLI_assert(!"Unhandled update flag, should never happen!");
- return "UNKNOWN";
+ return NULL;
}
/* Data-Based Tagging */
diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h
index eea69502baa..acfc8d19bc7 100644
--- a/source/blender/depsgraph/intern/node/deg_node.h
+++ b/source/blender/depsgraph/intern/node/deg_node.h
@@ -29,7 +29,6 @@
#include "DEG_depsgraph_build.h"
-struct GHash;
struct ID;
struct Scene;
diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h
index e6eb91a6b2d..35184253f5c 100644
--- a/source/blender/depsgraph/intern/node/deg_node_id.h
+++ b/source/blender/depsgraph/intern/node/deg_node_id.h
@@ -26,6 +26,8 @@
#include "intern/node/deg_node.h"
#include "BLI_sys_types.h"
+struct GHash;
+
namespace DEG {
struct ComponentNode;
diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h
index b0776d186bb..87c1a7f10a1 100644
--- a/source/blender/depsgraph/intern/node/deg_node_operation.h
+++ b/source/blender/depsgraph/intern/node/deg_node_operation.h
@@ -28,7 +28,6 @@
#include "intern/depsgraph_type.h"
struct Depsgraph;
-struct ID;
namespace DEG {
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index fc91ac371cb..9b0f5f743f6 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -328,6 +328,7 @@ data_to_c_simple(modes/shaders/overlay_face_wireframe_geom.glsl SRC)
data_to_c_simple(modes/shaders/overlay_face_wireframe_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_camera_image_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_camera_image_vert.glsl SRC)
+data_to_c_simple(modes/shaders/object_color_axes_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_empty_axes_vert.glsl SRC)
data_to_c_simple(modes/shaders/object_empty_image_frag.glsl SRC)
data_to_c_simple(modes/shaders/object_empty_image_vert.glsl SRC)
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index 6cae9ceb7d6..34d3ae1d207 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -26,28 +26,20 @@
#include "BLI_sys_types.h" /* for bool */
struct ARegion;
-struct Base;
struct DRWInstanceDataList;
-struct DRWPass;
struct Depsgraph;
struct DrawEngineType;
struct GPUMaterial;
struct GPUOffScreen;
struct GPUViewport;
struct ID;
-struct IDProperty;
struct Main;
-struct Material;
struct Object;
-struct RegionView3D;
struct RenderEngine;
struct RenderEngineType;
struct Scene;
struct View3D;
-struct ViewContext;
struct ViewLayer;
-struct ViewportEngineData;
-struct WorkSpace;
struct bContext;
struct rcti;
@@ -166,8 +158,8 @@ 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_gpu_context);
-void DRW_gawain_render_context_disable(void *re_gpu_context);
+void DRW_gpu_render_context_enable(void *re_gpu_context);
+void DRW_gpu_render_context_disable(void *re_gpu_context);
void DRW_deferred_shader_remove(struct GPUMaterial *mat);
diff --git a/source/blender/draw/DRW_select_buffer.h b/source/blender/draw/DRW_select_buffer.h
index 4aa1c403710..0ad13af81ba 100644
--- a/source/blender/draw/DRW_select_buffer.h
+++ b/source/blender/draw/DRW_select_buffer.h
@@ -30,7 +30,6 @@ struct Base;
struct Depsgraph;
struct Object;
struct View3D;
-struct ViewLayer;
struct rcti;
typedef struct SELECTID_ObjectData {
@@ -58,9 +57,6 @@ struct ObjectOffsets {
};
struct SELECTID_Context {
- struct GPUFrameBuffer *framebuffer_select_id;
- struct GPUTexture *texture_u32;
-
/* All context objects */
struct Object **objects;
uint objects_len;
@@ -131,7 +127,4 @@ void DRW_select_buffer_context_create(struct Base **bases,
const uint bases_len,
short select_mode);
-/* select_engine.c */
-struct SELECTID_Context *DRW_select_engine_context_get(void);
-
#endif /* __DRW_SELECT_BUFFER_H__ */
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 93521c71127..0ca1e0b2858 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -509,7 +509,7 @@ void EEVEE_downsample_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int le
}
/**
- * Simple downsampling algorithm for cubemap. Reconstruct mip chain up to mip level.
+ * Simple down-sampling algorithm for cubemap. Reconstruct mip chain up to mip level.
*/
void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, GPUTexture *texture_src, int level)
{
@@ -580,7 +580,7 @@ void EEVEE_draw_effects(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
/* NOTE: Lookdev drawing happens before TAA but after
* motion blur and dof to avoid distortions.
* Velocity resolve use a hack to exclude lookdev
- * spheres from creating shimering reprojection vectors. */
+ * spheres from creating shimmering re-projection vectors. */
EEVEE_lookdev_draw(vedata);
EEVEE_velocity_resolve(vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index c82a112b343..05aea652591 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -80,8 +80,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_gpu_context);
-extern void DRW_gawain_render_context_disable(void *re_gpu_context);
+extern void DRW_gpu_render_context_enable(void *re_gpu_context);
+extern void DRW_gpu_render_context_disable(void *re_gpu_context);
typedef struct EEVEE_LightBake {
Depsgraph *depsgraph;
@@ -138,7 +138,7 @@ typedef struct EEVEE_LightBake {
float vis_res;
/** Result of previous light bounce. */
GPUTexture *grid_prev;
- /** Pointer to the id.data of the probe object. */
+ /** Pointer to the owner_id of the probe object. */
LightProbe **grid_prb;
/* Reflection probe */
@@ -148,7 +148,7 @@ typedef struct EEVEE_LightBake {
int ref_cube_res;
/** Index of the current cube. */
int cube_offset;
- /** Pointer to the id.data of the probe object. */
+ /** Pointer to the owner_id of the probe object. */
LightProbe **cube_prb;
/* Dummy Textures */
@@ -412,7 +412,7 @@ static void eevee_lightbake_context_enable(EEVEE_LightBake *lbake)
if (lbake->gpu_context == NULL) {
lbake->gpu_context = GPU_context_create(0);
}
- DRW_gawain_render_context_enable(lbake->gpu_context);
+ DRW_gpu_render_context_enable(lbake->gpu_context);
}
else {
DRW_opengl_context_enable();
@@ -422,7 +422,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->gpu_context);
+ DRW_gpu_render_context_disable(lbake->gpu_context);
DRW_opengl_render_context_disable(lbake->gl_context);
}
else {
@@ -654,7 +654,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->gpu_context);
+ DRW_gpu_render_context_enable(lbake->gpu_context);
}
else if (!lbake->resource_only) {
DRW_opengl_context_enable();
@@ -675,8 +675,8 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake)
}
if (lbake->gpu_context) {
- DRW_gawain_render_context_disable(lbake->gpu_context);
- DRW_gawain_render_context_enable(lbake->gpu_context);
+ DRW_gpu_render_context_disable(lbake->gpu_context);
+ DRW_gpu_render_context_enable(lbake->gpu_context);
GPU_context_discard(lbake->gpu_context);
}
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.h b/source/blender/draw/engines/eevee/eevee_lightcache.h
index 5aea712a910..ede2de13dce 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.h
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.h
@@ -26,7 +26,6 @@
#include "BLI_sys_types.h" /* for bool */
struct EEVEE_Data;
-struct EEVEE_LightBake;
struct EEVEE_ViewLayerData;
struct LightCache;
struct Scene;
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 2026b44fe87..8b1309e8537 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -1213,7 +1213,7 @@ void EEVEE_lightbake_filter_visibility(EEVEE_ViewLayerData *sldata,
DRW_draw_pass(psl->probe_visibility_compute);
}
-/* Actually a simple downsampling */
+/* Actually a simple down-sampling. */
static void downsample_planar(void *vedata, int level)
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index c15872b31fa..0bfc23b8354 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -779,7 +779,7 @@ static void eevee_light_setup(Object *ob, EEVEE_Light *evli)
/**
* Special ball distribution:
- * Point are distributed in a way that when they are orthogonaly
+ * Point are distributed in a way that when they are orthogonally
* projected into any plane, the resulting distribution is (close to)
* a uniform disc distribution.
*/
diff --git a/source/blender/draw/engines/eevee/eevee_lut.c b/source/blender/draw/engines/eevee/eevee_lut.c
index 8db45e4cee6..b380269db99 100644
--- a/source/blender/draw/engines/eevee/eevee_lut.c
+++ b/source/blender/draw/engines/eevee/eevee_lut.c
@@ -21,6 +21,8 @@
* \ingroup gpu
*/
+#include "eevee_lut.h" /* own include */
+
const float ltc_mat_ggx[64 * 64 * 4] = {
1.000000, 0.000000, 0.000000, 0.000020, 1.000000, 0.000000, 0.000000, 0.000504,
1.000000, 0.000000, 0.000000, 0.002016, 1.000000, 0.000000, 0.000000, 0.004535,
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 27edd44075b..3cdafee95a2 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -30,7 +30,6 @@ struct EEVEE_ShadowCasterBuffer;
struct GPUFrameBuffer;
struct Object;
struct RenderLayer;
-struct RenderResult;
extern struct DrawEngineType draw_engine_eevee_type;
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index b0608343ab3..33e6d73eeeb 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -349,13 +349,13 @@ void DRW_gpencil_freecache(struct Object *ob)
}
}
- /* clear all frames derived data */
- for (int i = 0; i < ob->runtime.tot_layers; i++) {
- bGPDframe *derived_gpf = &ob->runtime.derived_frames[i];
- BKE_gpencil_free_frame_runtime_data(derived_gpf);
- derived_gpf = NULL;
+ /* clear all frames evaluated data */
+ for (int i = 0; i < ob->runtime.gpencil_tot_layers; i++) {
+ bGPDframe *gpf_eval = &ob->runtime.gpencil_evaluated_frames[i];
+ BKE_gpencil_free_frame_runtime_data(gpf_eval);
+ gpf_eval = NULL;
}
- ob->runtime.tot_layers = 0;
- MEM_SAFE_FREE(ob->runtime.derived_frames);
+ ob->runtime.gpencil_tot_layers = 0;
+ MEM_SAFE_FREE(ob->runtime.gpencil_evaluated_frames);
}
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
index 1ec02cac109..541a9e31586 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_cache_impl.c
@@ -821,7 +821,7 @@ void gpencil_get_edit_geom(struct GpencilBatchCacheElem *be,
void gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be,
bGPDstroke *gps,
float alpha,
- short UNUSED(dflag))
+ const bool hide_select)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
Object *ob = draw_ctx->obact;
@@ -866,7 +866,7 @@ void gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be,
copy_v4_v4(fcolor, selectColor);
}
else {
- if (pt->flag & GP_SPOINT_SELECT) {
+ if ((pt->flag & GP_SPOINT_SELECT) && (!hide_select)) {
copy_v4_v4(fcolor, selectColor);
}
else {
diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
index 85ad1689c23..bef72b9a054 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_utils.c
@@ -65,8 +65,7 @@
static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
tGPencilObjectCache *cache_ob,
GpencilBatchCache *cache,
- bGPdata *gpd,
- int cfra_eval)
+ bGPdata *gpd)
{
if (!cache->is_dirty) {
return;
@@ -88,13 +87,13 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
cache_ob->tot_vertex = 0;
cache_ob->tot_triangles = 0;
- int derived_idx = 0;
+ int idx_eval = 0;
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
bGPDframe *init_gpf = NULL;
const bool is_onion = ((do_onion) && (gpl->onion_flag & GP_LAYER_ONIONSKIN));
if (gpl->flag & GP_LAYER_HIDE) {
- derived_idx++;
+ idx_eval++;
continue;
}
@@ -103,7 +102,7 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
init_gpf = gpl->frames.first;
}
else {
- init_gpf = &ob->runtime.derived_frames[derived_idx];
+ init_gpf = &ob->runtime.gpencil_evaluated_frames[idx_eval];
}
if (init_gpf == NULL) {
@@ -119,7 +118,7 @@ static void gpencil_calc_vertex(GPENCIL_StorageList *stl,
break;
}
}
- derived_idx++;
+ idx_eval++;
}
cache->b_fill.tot_vertex = cache_ob->tot_triangles * 3;
@@ -939,6 +938,17 @@ static void gpencil_add_editpoints_vertexdata(GpencilBatchCache *cache,
{
const DRWContextState *draw_ctx = DRW_context_state_get();
View3D *v3d = draw_ctx->v3d;
+ ToolSettings *ts = draw_ctx->scene->toolsettings;
+ const bool use_sculpt_mask = (GPENCIL_SCULPT_MODE(gpd) && (ts->gpencil_selectmode_sculpt &
+ (GP_SCULPT_MASK_SELECTMODE_POINT |
+ GP_SCULPT_MASK_SELECTMODE_STROKE |
+ GP_SCULPT_MASK_SELECTMODE_SEGMENT)));
+
+ const bool show_sculpt_points = (GPENCIL_SCULPT_MODE(gpd) &&
+ (ts->gpencil_selectmode_sculpt &
+ (GP_SCULPT_MASK_SELECTMODE_POINT |
+ GP_SCULPT_MASK_SELECTMODE_SEGMENT)));
+
MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
/* alpha factor for edit points/line to make them more subtle */
@@ -951,11 +961,24 @@ static void gpencil_add_editpoints_vertexdata(GpencilBatchCache *cache,
}
const bool is_weight_paint = (gpd) && (gpd->flag & GP_DATA_STROKE_WEIGHTMODE);
+ /* If Sculpt mode and the mask is disabled, the select must be hidden. */
+ const bool hide_select = GPENCIL_SCULPT_MODE(gpd) && !use_sculpt_mask;
+
+ /* Show Edit points if:
+ * Edit mode: Not in Stroke selection mode
+ * Sculpt mode: Not in Stroke mask mode and any other mask mode enabled
+ * Weight mode: Always
+ */
+ const bool show_points = (show_sculpt_points) || (is_weight_paint) ||
+ (GPENCIL_EDIT_MODE(gpd) &&
+ ((ts->gpencil_selectmode_edit & GP_SELECTMODE_STROKE) == 0));
+
if (cache->is_dirty) {
if ((obact == ob) && ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) &&
(v3d->gp_flag & V3D_GP_SHOW_EDIT_LINES)) {
+
/* line of the original stroke */
- gpencil_get_edlin_geom(&cache->b_edlin, gps, edit_alpha, gpd->flag);
+ gpencil_get_edlin_geom(&cache->b_edlin, gps, edit_alpha, hide_select);
/* add to list of groups */
cache->grp_cache = gpencil_group_cache_add(cache->grp_cache,
@@ -968,6 +991,12 @@ static void gpencil_add_editpoints_vertexdata(GpencilBatchCache *cache,
&cache->grp_size,
&cache->grp_used);
}
+
+ /* If the points are hidden return. */
+ if ((!show_points) || (hide_select)) {
+ return;
+ }
+
/* edit points */
if ((gps->flag & GP_STROKE_SELECT) || (is_weight_paint)) {
if ((gpl->flag & GP_LAYER_UNLOCK_COLOR) ||
@@ -1797,7 +1826,7 @@ void gpencil_populate_multiedit(GPENCIL_e_data *e_data,
const bool playing = stl->storage->is_playing;
/* calc max size of VBOs */
- gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval);
+ gpencil_calc_vertex(stl, cache_ob, cache, gpd);
/* draw strokes */
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
@@ -1860,6 +1889,14 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
const ViewLayer *view_layer = DEG_get_evaluated_view_layer(draw_ctx->depsgraph);
Scene *scene = draw_ctx->scene;
+ /* TODO: Review why is needed this recalc when render cycles + GP object in background.
+ * We need these lines to keep running the background render, but asap we get an alternative
+ * solution, we must remove it and keep all logic inside gpencil_modifier module. (antoniov)
+ */
+ if (ob->runtime.gpencil_tot_layers == 0) {
+ BKE_gpencil_modifiers_calc(draw_ctx->depsgraph, draw_ctx->scene, ob);
+ }
+
/* Use original data to shared in edit/transform operators */
bGPdata *gpd_eval = (bGPdata *)ob->data;
bGPdata *gpd = (bGPdata *)DEG_get_original_id(&gpd_eval->id);
@@ -1867,7 +1904,7 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
View3D *v3d = draw_ctx->v3d;
int cfra_eval = (int)DEG_get_ctime(draw_ctx->depsgraph);
- bGPDframe *derived_gpf = NULL;
+ bGPDframe *gpf_eval = NULL;
const bool overlay = v3d != NULL ? (bool)((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0) : true;
const bool time_remap = BKE_gpencil_has_time_modifiers(ob);
@@ -1887,7 +1924,7 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
}
/* calc max size of VBOs */
- gpencil_calc_vertex(stl, cache_ob, cache, gpd, cfra_eval);
+ gpencil_calc_vertex(stl, cache_ob, cache, gpd);
/* draw normal strokes */
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) {
@@ -1936,9 +1973,9 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
opacity = opacity * v3d->overlay.gpencil_fade_layer;
}
- /* Get derived frames array data */
- int derived_idx = BLI_findindex(&gpd->layers, gpl);
- derived_gpf = &ob->runtime.derived_frames[derived_idx];
+ /* Get evaluated frames array data */
+ int idx_eval = BLI_findindex(&gpd->layers, gpl);
+ gpf_eval = &ob->runtime.gpencil_evaluated_frames[idx_eval];
/* draw onion skins */
if (!ID_IS_LINKED(&gpd->id)) {
@@ -1952,17 +1989,8 @@ void gpencil_populate_datablock(GPENCIL_e_data *e_data,
}
}
/* draw normal strokes */
- gpencil_draw_strokes(cache,
- e_data,
- vedata,
- ob,
- gpd,
- gpl,
- derived_gpf,
- opacity,
- gpl->tintcolor,
- false,
- cache_ob);
+ gpencil_draw_strokes(
+ cache, e_data, vedata, ob, gpd, gpl, gpf_eval, opacity, gpl->tintcolor, false, cache_ob);
}
/* create batchs and shading groups */
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index b0898cb33f3..d03f975ca37 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -405,10 +405,10 @@ void GPENCIL_cache_init(void *vedata)
}
/* 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);
- stl->storage->simplify_blend = GP_SIMPLIFY_BLEND(scene, stl->storage->is_playing);
+ stl->storage->simplify_fill = GPENCIL_SIMPLIFY_FILL(scene, stl->storage->is_playing);
+ stl->storage->simplify_modif = GPENCIL_SIMPLIFY_MODIF(scene, stl->storage->is_playing);
+ stl->storage->simplify_fx = GPENCIL_SIMPLIFY_FX(scene, stl->storage->is_playing);
+ stl->storage->simplify_blend = GPENCIL_SIMPLIFY_BLEND(scene, stl->storage->is_playing);
/* xray mode */
if (v3d) {
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index c3167e21f27..f29e83f64cf 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -28,15 +28,14 @@
struct GPENCIL_Data;
struct GPENCIL_StorageList;
struct MaterialGPencilStyle;
-struct ModifierData;
struct Object;
struct RenderEngine;
struct RenderLayer;
struct bGPDstroke;
-struct tGPspoint;
-struct GpencilBatchCache;
-struct GpencilBatchCacheElem;
-struct GpencilBatchGroup;
+
+struct GPUBatch;
+struct GPUVertBuf;
+struct GPUVertFormat;
#define GPENCIL_CACHE_BLOCK_SIZE 8
#define GPENCIL_MAX_SHGROUPS 65536
@@ -327,6 +326,64 @@ typedef struct GPENCIL_e_data {
} GPENCIL_e_data; /* Engine data */
+/* GPUBatch Cache Element */
+typedef struct GpencilBatchCacheElem {
+ GPUBatch *batch;
+ GPUVertBuf *vbo;
+ int vbo_len;
+ /* attr ids */
+ GPUVertFormat *format;
+ uint pos_id;
+ uint color_id;
+ uint thickness_id;
+ uint uvdata_id;
+ uint prev_pos_id;
+
+ /* size for VBO alloc */
+ int tot_vertex;
+} GpencilBatchCacheElem;
+
+/* Defines each batch group to define later the shgroup */
+typedef struct GpencilBatchGroup {
+ struct bGPDlayer *gpl; /* reference to original layer */
+ struct bGPDframe *gpf; /* reference to original frame */
+ struct bGPDstroke *gps; /* reference to original stroke */
+ short type; /* type of element */
+ bool onion; /* the group is part of onion skin */
+ int vertex_idx; /* index of vertex data */
+} GpencilBatchGroup;
+
+typedef enum GpencilBatchGroup_Type {
+ eGpencilBatchGroupType_Stroke = 1,
+ eGpencilBatchGroupType_Point = 2,
+ eGpencilBatchGroupType_Fill = 3,
+ eGpencilBatchGroupType_Edit = 4,
+ eGpencilBatchGroupType_Edlin = 5,
+} GpencilBatchGroup_Type;
+
+/* Runtime data for GPU and evaluated frames after applying modifiers */
+typedef struct GpencilBatchCache {
+ GpencilBatchCacheElem b_stroke;
+ GpencilBatchCacheElem b_point;
+ GpencilBatchCacheElem b_fill;
+ GpencilBatchCacheElem b_edit;
+ GpencilBatchCacheElem b_edlin;
+
+ /** Cache is dirty */
+ bool is_dirty;
+ /** Edit mode flag */
+ bool is_editmode;
+ /** Last cache frame */
+ int cache_frame;
+
+ /** Total groups in arrays */
+ int grp_used;
+ /** Max size of the array */
+ int grp_size;
+ /** Array of cache elements */
+ struct GpencilBatchGroup *grp_cache;
+} GpencilBatchCache;
+
/* general drawing functions */
struct DRWShadingGroup *gpencil_shgroup_stroke_create(struct GPENCIL_Data *vedata,
struct DRWPass *pass,
@@ -380,7 +437,7 @@ void gpencil_get_edit_geom(struct GpencilBatchCacheElem *be,
void gpencil_get_edlin_geom(struct GpencilBatchCacheElem *be,
struct bGPDstroke *gps,
float alpha,
- short dflag);
+ const bool hide_select);
struct GPUBatch *gpencil_get_buffer_stroke_geom(struct bGPdata *gpd, short thickness);
struct GPUBatch *gpencil_get_buffer_fill_geom(struct bGPdata *gpd);
diff --git a/source/blender/draw/engines/select/select_draw_utils.c b/source/blender/draw/engines/select/select_draw_utils.c
index 268cd60a8aa..6a51c28c242 100644
--- a/source/blender/draw/engines/select/select_draw_utils.c
+++ b/source/blender/draw/engines/select/select_draw_utils.c
@@ -44,48 +44,6 @@
/** \name Draw Utilities
* \{ */
-static void select_id_framebuffer_setup(struct SELECTID_Context *select_ctx)
-{
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- int size[2];
- size[0] = GPU_texture_width(dtxl->depth);
- size[1] = GPU_texture_height(dtxl->depth);
-
- if (select_ctx->framebuffer_select_id == NULL) {
- select_ctx->framebuffer_select_id = GPU_framebuffer_create();
- }
-
- if ((select_ctx->texture_u32 != NULL) &&
- ((GPU_texture_width(select_ctx->texture_u32) != size[0]) ||
- (GPU_texture_height(select_ctx->texture_u32) != size[1]))) {
- GPU_texture_free(select_ctx->texture_u32);
- select_ctx->texture_u32 = NULL;
- }
-
- /* Make sure the depth texture is attached.
- * It may disappear when loading another Blender session. */
- GPU_framebuffer_texture_attach(select_ctx->framebuffer_select_id, dtxl->depth, 0, 0);
-
- if (select_ctx->texture_u32 == NULL) {
- select_ctx->texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL);
- GPU_framebuffer_texture_attach(
- select_ctx->framebuffer_select_id, select_ctx->texture_u32, 0, 0);
-
- GPU_framebuffer_check_valid(select_ctx->framebuffer_select_id, NULL);
- }
-}
-
-/* Remove all tags from drawn or culled objects. */
-void select_id_context_clear(struct SELECTID_Context *select_ctx)
-{
- select_ctx->objects_drawn_len = 0;
- select_ctx->index_drawn_len = 1;
- select_id_framebuffer_setup(select_ctx);
- GPU_framebuffer_bind(select_ctx->framebuffer_select_id);
- GPU_framebuffer_clear_color_depth(
- select_ctx->framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
-}
-
void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3])
{
BoundBox *bb;
@@ -104,13 +62,19 @@ void select_id_object_min_max(Object *obj, float r_min[3], float r_max[3])
short select_id_get_object_select_mode(Scene *scene, Object *ob)
{
short r_select_mode = 0;
- if (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)) {
+ if (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT)) {
Mesh *me_orig = DEG_get_original_object(ob)->data;
if (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) {
r_select_mode = SCE_SELECT_FACE;
}
- if (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) {
- r_select_mode |= SCE_SELECT_VERTEX;
+ else if (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) {
+ r_select_mode = SCE_SELECT_VERTEX;
+ }
+ }
+ else if (ob->mode & OB_MODE_TEXTURE_PAINT) {
+ Mesh *me_orig = DEG_get_original_object(ob)->data;
+ if (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL) {
+ r_select_mode = SCE_SELECT_FACE;
}
}
else {
@@ -151,12 +115,11 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl,
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
- struct GPUBatch *geom_faces;
- DRWShadingGroup *face_shgrp;
if (select_mode & SCE_SELECT_FACE) {
- geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat);
+ struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
+ DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat);
DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset);
+ DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob);
if (draw_facedot) {
struct GPUBatch *geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
@@ -165,11 +128,13 @@ static void draw_select_id_edit_mesh(SELECTID_StorageList *stl,
*r_face_offset = initial_offset + em->bm->totface;
}
else {
- geom_faces = DRW_mesh_batch_cache_get_surface(me);
- face_shgrp = stl->g_data->shgrp_face_unif;
+ if (ob->dt >= OB_SOLID) {
+ struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_surface(me);
+ DRWShadingGroup *face_shgrp = stl->g_data->shgrp_face_unif;
+ DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob);
+ }
*r_face_offset = initial_offset;
}
- DRW_shgroup_call_no_cull(face_shgrp, geom_faces, ob);
/* Unlike faces, only draw edges if edge select mode. */
if (select_mode & SCE_SELECT_EDGE) {
diff --git a/source/blender/draw/engines/select/select_engine.c b/source/blender/draw/engines/select/select_engine.c
index 4c158312e0f..c294bba2083 100644
--- a/source/blender/draw/engines/select/select_engine.c
+++ b/source/blender/draw/engines/select/select_engine.c
@@ -40,10 +40,13 @@
/* *********** STATIC *********** */
static struct {
+ struct GPUFrameBuffer *framebuffer_select_id;
+ struct GPUTexture *texture_u32;
+
SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN];
struct SELECTID_Context context;
uint runtime_new_objects;
-} e_data = {{{NULL}}}; /* Engine data */
+} e_data = {NULL}; /* Engine data */
/* Shaders */
extern char datatoc_common_view_lib_glsl[];
@@ -51,6 +54,41 @@ extern char datatoc_selection_id_3D_vert_glsl[];
extern char datatoc_selection_id_frag_glsl[];
/* -------------------------------------------------------------------- */
+/** \name Utils
+ * \{ */
+
+static void select_engine_framebuffer_setup(void)
+{
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ int size[2];
+ size[0] = GPU_texture_width(dtxl->depth);
+ size[1] = GPU_texture_height(dtxl->depth);
+
+ if (e_data.framebuffer_select_id == NULL) {
+ e_data.framebuffer_select_id = GPU_framebuffer_create();
+ }
+
+ if ((e_data.texture_u32 != NULL) && ((GPU_texture_width(e_data.texture_u32) != size[0]) ||
+ (GPU_texture_height(e_data.texture_u32) != size[1]))) {
+ GPU_texture_free(e_data.texture_u32);
+ e_data.texture_u32 = NULL;
+ }
+
+ /* Make sure the depth texture is attached.
+ * It may disappear when loading another Blender session. */
+ GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0);
+
+ if (e_data.texture_u32 == NULL) {
+ e_data.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL);
+ GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0);
+
+ GPU_framebuffer_check_valid(e_data.framebuffer_select_id, NULL);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Engine Functions
* \{ */
@@ -125,6 +163,13 @@ static void select_cache_init(void *vedata)
if (e_data.context.select_mode == -1) {
e_data.context.select_mode = select_id_get_object_select_mode(draw_ctx->scene,
draw_ctx->obact);
+ if (e_data.context.select_mode == 0) {
+ /* Need for sampling weights. */
+ if (draw_ctx->object_mode & OB_MODE_WEIGHT_PAINT) {
+ e_data.context.select_mode = SCE_SELECT_FACE;
+ }
+ }
+
BLI_assert(e_data.context.select_mode != 0);
}
@@ -186,8 +231,13 @@ static void select_cache_init(void *vedata)
float(*persmat)[4] = draw_ctx->rv3d->persmat;
e_data.context.is_dirty = !compare_m4m4(e_data.context.persmat, persmat, FLT_EPSILON);
if (e_data.context.is_dirty) {
+ /* Remove all tags from drawn or culled objects. */
copy_m4_m4(e_data.context.persmat, persmat);
- select_id_context_clear(&e_data.context);
+ e_data.context.objects_drawn_len = 0;
+ e_data.context.index_drawn_len = 1;
+ select_engine_framebuffer_setup();
+ GPU_framebuffer_bind(e_data.framebuffer_select_id);
+ GPU_framebuffer_clear_color_depth(e_data.framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
}
e_data.runtime_new_objects = 0;
}
@@ -204,14 +254,14 @@ static void select_cache_populate(void *vedata, Object *ob)
/* The object indices have already been drawn. Fill depth pass.
* Opti: Most of the time this depth pass is not used. */
struct Mesh *me = ob->data;
- struct GPUBatch *geom_faces;
if (e_data.context.select_mode & SCE_SELECT_FACE) {
- geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
+ struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
+ DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat);
}
- else {
- geom_faces = DRW_mesh_batch_cache_get_surface(me);
+ else if (ob->dt >= OB_SOLID) {
+ struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_surface(me);
+ DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat);
}
- DRW_shgroup_call_obmat(stl->g_data->shgrp_depth_only, geom_faces, ob->obmat);
if (e_data.context.select_mode & SCE_SELECT_EDGE) {
struct GPUBatch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
@@ -283,7 +333,7 @@ static void select_draw_scene(void *vedata)
}
/* Setup framebuffer */
- GPU_framebuffer_bind(e_data.context.framebuffer_select_id);
+ GPU_framebuffer_bind(e_data.framebuffer_select_id);
DRW_draw_pass(psl->select_id_face_pass);
@@ -306,8 +356,8 @@ static void select_engine_free(void)
DRW_SHADER_FREE_SAFE(sh_data->select_id_uniform);
}
- DRW_TEXTURE_FREE_SAFE(e_data.context.texture_u32);
- GPU_FRAMEBUFFER_FREE_SAFE(e_data.context.framebuffer_select_id);
+ DRW_TEXTURE_FREE_SAFE(e_data.texture_u32);
+ GPU_FRAMEBUFFER_FREE_SAFE(e_data.framebuffer_select_id);
MEM_SAFE_FREE(e_data.context.objects);
MEM_SAFE_FREE(e_data.context.index_offsets);
MEM_SAFE_FREE(e_data.context.objects_drawn);
@@ -368,6 +418,16 @@ struct SELECTID_Context *DRW_select_engine_context_get(void)
return &e_data.context;
}
+GPUFrameBuffer *DRW_engine_select_framebuffer_get(void)
+{
+ return e_data.framebuffer_select_id;
+}
+
+GPUTexture *DRW_engine_select_texture_get(void)
+{
+ return e_data.texture_u32;
+}
+
/** \} */
#undef SELECT_ENGINE
diff --git a/source/blender/draw/engines/select/select_engine.h b/source/blender/draw/engines/select/select_engine.h
index 5b900ccaf27..79139d9deaf 100644
--- a/source/blender/draw/engines/select/select_engine.h
+++ b/source/blender/draw/engines/select/select_engine.h
@@ -26,4 +26,9 @@
extern DrawEngineType draw_engine_select_type;
extern RenderEngineType DRW_engine_viewport_select_type;
-#endif /* __SELECT_ID_ENGINE_H__ */
+struct SELECTID_Context *DRW_select_engine_context_get(void);
+
+struct GPUFrameBuffer *DRW_engine_select_framebuffer_get(void);
+struct GPUTexture *DRW_engine_select_texture_get(void);
+
+#endif /* __SELECT_ENGINE_H__ */
diff --git a/source/blender/draw/engines/select/select_private.h b/source/blender/draw/engines/select/select_private.h
index e48ce4314ae..642cd6ffc56 100644
--- a/source/blender/draw/engines/select/select_private.h
+++ b/source/blender/draw/engines/select/select_private.h
@@ -66,7 +66,6 @@ typedef struct SELECTID_PrivateData {
} SELECTID_PrivateData; /* Transient data */
/* select_draw_utils.c */
-void select_id_context_clear(struct SELECTID_Context *select_ctx);
void select_id_object_min_max(struct Object *obj, float r_min[3], float r_max[3]);
short select_id_get_object_select_mode(Scene *scene, Object *ob);
void select_id_draw_object(void *vedata,
diff --git a/source/blender/draw/engines/select/shaders/selection_id_frag.glsl b/source/blender/draw/engines/select/shaders/selection_id_frag.glsl
index ea86ddc7301..a84bbbb2cac 100644
--- a/source/blender/draw/engines/select/shaders/selection_id_frag.glsl
+++ b/source/blender/draw/engines/select/shaders/selection_id_frag.glsl
@@ -1,14 +1,15 @@
#ifdef UNIFORM_ID
uniform int id;
-# define id floatBitsToUint(intBitsToFloat(id))
+# define _id floatBitsToUint(intBitsToFloat(id))
#else
flat in uint id;
+# define _id id
#endif
out uint fragColor;
void main()
{
- fragColor = id;
+ fragColor = _id;
}
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
index a1f80440404..fd4cea4279a 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_deferred_composite_frag.glsl
@@ -5,7 +5,8 @@ uniform sampler2D materialBuffer;
uniform sampler2D normalBuffer;
/* normalBuffer contains viewport normals */
uniform sampler2D cavityBuffer;
-uniform sampler2D matcapImage;
+uniform sampler2D matcapDiffuseImage;
+uniform sampler2D matcapSpecularImage;
uniform vec2 invertedViewportSize;
uniform vec4 viewvecs[3];
@@ -55,8 +56,15 @@ void main()
normal_viewport = (metallic > 0.0) ? normal_viewport : -normal_viewport;
bool flipped = world_data.matcap_orientation != 0;
vec2 matcap_uv = matcap_uv_compute(I_vs, normal_viewport, flipped);
- vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb;
- vec3 shaded_color = matcap * base_color;
+ vec3 matcap_diffuse = textureLod(matcapDiffuseImage, matcap_uv, 0.0).rgb;
+
+# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
+ vec3 matcap_specular = textureLod(matcapSpecularImage, matcap_uv, 0.0).rgb;
+# else
+ vec3 matcap_specular = vec3(0.0);
+# endif
+
+ vec3 shaded_color = matcap_diffuse * base_color + matcap_specular;
#elif defined(V3D_LIGHTING_STUDIO)
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 c78b2182d04..3333dfeff38 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
@@ -27,7 +27,8 @@ in vec2 uv_interp;
in vec3 vertexColor;
#endif
#ifdef V3D_LIGHTING_MATCAP
-uniform sampler2D matcapImage;
+uniform sampler2D matcapDiffuseImage;
+uniform sampler2D matcapSpecularImage;
#endif
layout(std140) uniform world_block
@@ -68,8 +69,13 @@ void main()
#elif defined(V3D_LIGHTING_MATCAP)
bool flipped = world_data.matcap_orientation != 0;
vec2 matcap_uv = matcap_uv_compute(I_vs, nor, flipped);
- vec3 matcap = textureLod(matcapImage, matcap_uv, 0.0).rgb;
- vec3 shaded_color = matcap * diffuse_color.rgb;
+ vec3 matcap_diffuse = textureLod(matcapDiffuseImage, matcap_uv, 0.0).rgb;
+# ifdef V3D_SHADING_SPECULAR_HIGHLIGHT
+ vec3 matcap_specular = textureLod(matcapSpecularImage, matcap_uv, 0.0).rgb;
+# else
+ vec3 matcap_specular = vec3(0.0);
+# endif
+ vec3 shaded_color = matcap_diffuse * diffuse_color.rgb + matcap_specular;
#elif defined(V3D_LIGHTING_STUDIO)
vec3 shaded_color = get_world_lighting(
diff --git a/source/blender/draw/engines/workbench/workbench_deferred.c b/source/blender/draw/engines/workbench/workbench_deferred.c
index add49462de1..c1c9d8b5a96 100644
--- a/source/blender/draw/engines/workbench/workbench_deferred.c
+++ b/source/blender/draw/engines/workbench/workbench_deferred.c
@@ -694,16 +694,22 @@ static void workbench_composite_uniforms(WORKBENCH_PrivateData *wpd, DRWShadingG
if (CAVITY_ENABLED(wpd)) {
DRW_shgroup_uniform_texture_ref(grp, "cavityBuffer", &e_data.cavity_buffer_tx);
}
- if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
+ if (workbench_is_specular_highlight_enabled(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
}
- if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
+ if (workbench_is_specular_highlight_enabled(wpd) || STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
}
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
- BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
+ BKE_studiolight_ensure_flag(wpd->studio_light,
+ STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE |
+ STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE);
DRW_shgroup_uniform_texture(
- grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture);
+ grp, "matcapDiffuseImage", wpd->studio_light->matcap_diffuse.gputexture);
+ if (workbench_is_specular_highlight_enabled(wpd)) {
+ DRW_shgroup_uniform_texture(
+ grp, "matcapSpecularImage", wpd->studio_light->matcap_specular.gputexture);
+ }
}
}
diff --git a/source/blender/draw/engines/workbench/workbench_forward.c b/source/blender/draw/engines/workbench/workbench_forward.c
index 4c1fce550e8..824c6e7bd76 100644
--- a/source/blender/draw/engines/workbench/workbench_forward.c
+++ b/source/blender/draw/engines/workbench/workbench_forward.c
@@ -186,11 +186,17 @@ WORKBENCH_MaterialData *workbench_forward_get_or_create_material_data(WORKBENCH_
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)wpd->viewvecs, 3);
workbench_material_copy(material, &material_template);
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
- BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
+ BKE_studiolight_ensure_flag(wpd->studio_light,
+ STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE |
+ STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE);
DRW_shgroup_uniform_texture(
- grp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture);
+ grp, "matcapDiffuseImage", wpd->studio_light->matcap_diffuse.gputexture);
+ if (workbench_is_specular_highlight_enabled(wpd)) {
+ DRW_shgroup_uniform_texture(
+ grp, "matcapSpecularImage", wpd->studio_light->matcap_specular.gputexture);
+ }
}
- if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) {
+ if (workbench_is_specular_highlight_enabled(wpd) || MATCAP_ENABLED(wpd)) {
DRW_shgroup_uniform_vec2(grp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
}
if (SHADOW_ENABLED(wpd)) {
@@ -528,11 +534,17 @@ static void workbench_forward_cache_populate_particles(WORKBENCH_Data *vedata, O
float hair_alpha = XRAY_ALPHA(wpd) * 0.33f;
DRW_shgroup_uniform_float_copy(shgrp, "alpha", hair_alpha);
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
- BKE_studiolight_ensure_flag(wpd->studio_light, STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE);
+ BKE_studiolight_ensure_flag(wpd->studio_light,
+ STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE |
+ STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE);
DRW_shgroup_uniform_texture(
- shgrp, "matcapImage", wpd->studio_light->equirect_radiance_gputexture);
+ shgrp, "matcapDiffuseImage", wpd->studio_light->matcap_diffuse.gputexture);
+ if (workbench_is_specular_highlight_enabled(wpd)) {
+ DRW_shgroup_uniform_texture(
+ shgrp, "matcapSpecularImage", wpd->studio_light->matcap_specular.gputexture);
+ }
}
- if (SPECULAR_HIGHLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) {
+ if (workbench_is_specular_highlight_enabled(wpd) || MATCAP_ENABLED(wpd)) {
DRW_shgroup_uniform_vec2(shgrp, "invertedViewportSize", DRW_viewport_invert_size_get(), 1);
}
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 6699a1954ba..e050877187e 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -79,7 +79,7 @@ void workbench_material_update_data(WORKBENCH_PrivateData *wpd,
/* V3D_SHADING_MATERIAL_COLOR or V3D_SHADING_TEXTURE_COLOR */
if (mat) {
data->alpha *= mat->a;
- if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
+ if (workbench_is_specular_highlight_enabled(wpd)) {
copy_v3_v3(data->base_color, &mat->r);
mul_v3_v3fl(data->diffuse_color, &mat->r, 1.0f - mat->metallic);
mul_v3_v3fl(data->specular_color, &mat->r, mat->metallic);
@@ -121,7 +121,7 @@ char *workbench_material_build_defines(WORKBENCH_PrivateData *wpd,
if (SSAO_ENABLED(wpd) || CURVATURE_ENABLED(wpd)) {
BLI_dynstr_append(ds, "#define WB_CAVITY\n");
}
- if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
+ if (workbench_is_specular_highlight_enabled(wpd)) {
BLI_dynstr_append(ds, "#define V3D_SHADING_SPECULAR_HIGHLIGHT\n");
}
if (STUDIOLIGHT_ENABLED(wpd)) {
@@ -195,11 +195,12 @@ int workbench_material_get_composite_shader_index(WORKBENCH_PrivateData *wpd)
/* NOTE: change MAX_COMPOSITE_SHADERS accordingly when modifying this function. */
int index = 0;
/* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
- index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light;
+ index = wpd->shading.light;
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_SHADOW, 1 << 2);
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_CAVITY, 1 << 3);
SET_FLAG_FROM_TEST(index, wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE, 1 << 4);
SET_FLAG_FROM_TEST(index, workbench_is_matdata_pass_enabled(wpd), 1 << 5);
+ SET_FLAG_FROM_TEST(index, workbench_is_specular_highlight_enabled(wpd), 1 << 6);
BLI_assert(index < MAX_COMPOSITE_SHADERS);
return index;
}
@@ -246,12 +247,13 @@ int workbench_material_get_accum_shader_index(WORKBENCH_PrivateData *wpd,
/* NOTE: change MAX_ACCUM_SHADERS accordingly when modifying this function. */
int index = 0;
/* 2 bits FLAT/STUDIO/MATCAP + Specular highlight */
- index = SPECULAR_HIGHLIGHT_ENABLED(wpd) ? 3 : wpd->shading.light;
+ index = wpd->shading.light;
SET_FLAG_FROM_TEST(index, use_textures, 1 << 2);
SET_FLAG_FROM_TEST(index, use_vertex_colors, 1 << 3);
SET_FLAG_FROM_TEST(index, is_hair, 1 << 4);
/* 1 bits SHADOWS (only facing factor) */
SET_FLAG_FROM_TEST(index, SHADOW_ENABLED(wpd), 1 << 5);
+ SET_FLAG_FROM_TEST(index, workbench_is_specular_highlight_enabled(wpd), 1 << 6);
BLI_assert(index < MAX_ACCUM_SHADERS);
return index;
}
@@ -333,7 +335,7 @@ void workbench_material_shgroup_uniform(WORKBENCH_PrivateData *wpd,
1);
}
- if (SPECULAR_HIGHLIGHT_ENABLED(wpd)) {
+ if (workbench_is_specular_highlight_enabled(wpd)) {
if (use_metallic) {
DRW_shgroup_uniform_float(grp, "materialMetallic", &material->metallic, 1);
}
diff --git a/source/blender/draw/engines/workbench/workbench_private.h b/source/blender/draw/engines/workbench/workbench_private.h
index 255b036eebb..d880d5d58b5 100644
--- a/source/blender/draw/engines/workbench/workbench_private.h
+++ b/source/blender/draw/engines/workbench/workbench_private.h
@@ -36,9 +36,9 @@
#define WORKBENCH_ENGINE "BLENDER_WORKBENCH"
#define M_GOLDEN_RATION_CONJUGATE 0.618033988749895
-#define MAX_COMPOSITE_SHADERS (1 << 6)
+#define MAX_COMPOSITE_SHADERS (1 << 7)
#define MAX_PREPASS_SHADERS (1 << 7)
-#define MAX_ACCUM_SHADERS (1 << 6)
+#define MAX_ACCUM_SHADERS (1 << 7)
#define MAX_CAVITY_SHADERS (1 << 3)
#define TEXTURE_DRAWING_ENABLED(wpd) (wpd->shading.color_type == V3D_SHADING_TEXTURE_COLOR)
@@ -77,9 +77,6 @@
#define IS_NAVIGATING(wpd) \
((DRW_context_state_get()->rv3d) && (DRW_context_state_get()->rv3d->rflag & RV3D_NAVIGATING))
-#define SPECULAR_HIGHLIGHT_ENABLED(wpd) \
- (STUDIOLIGHT_ENABLED(wpd) && (wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT) && \
- (!STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)))
#define OBJECT_OUTLINE_ENABLED(wpd) (wpd->shading.flag & V3D_SHADING_OBJECT_OUTLINE)
#define OBJECT_ID_PASS_ENABLED(wpd) (OBJECT_OUTLINE_ENABLED(wpd) || CURVATURE_ENABLED(wpd))
#define NORMAL_VIEWPORT_COMP_PASS_ENABLED(wpd) \
@@ -316,6 +313,16 @@ typedef struct WORKBENCH_ObjectData {
} WORKBENCH_ObjectData;
/* inline helper functions */
+BLI_INLINE bool workbench_is_specular_highlight_enabled(WORKBENCH_PrivateData *wpd)
+{
+ if ((wpd->shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT)) {
+ if (STUDIOLIGHT_ENABLED(wpd) || MATCAP_ENABLED(wpd)) {
+ return (wpd->studio_light->flag & STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS) != 0;
+ }
+ }
+ return false;
+}
+
BLI_INLINE bool workbench_is_taa_enabled(WORKBENCH_PrivateData *wpd)
{
if (DRW_state_is_image_render()) {
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 8e4ca1cefab..a289152807c 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -61,7 +61,6 @@
#include "DEG_depsgraph.h"
-struct DRWTextStore;
struct DefaultFramebufferList;
struct DefaultTextureList;
struct GPUBatch;
@@ -70,12 +69,9 @@ struct GPUMaterial;
struct GPUShader;
struct GPUTexture;
struct GPUUniformBuffer;
-struct LightEngineData;
struct Object;
struct ParticleSystem;
struct RenderEngineType;
-struct ViewportEngineData;
-struct ViewportEngineData_Info;
struct bContext;
struct rcti;
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index bad4b55eb1a..520932bc429 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -4001,7 +4001,7 @@ GPUBatch *DRW_cache_cursor_get(bool crosshair_lines)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Batch Cache Impl. common
+/** \name Batch Cache Implementation (common)
* \{ */
void drw_batch_cache_validate(Object *ob)
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 5dadcdc1457..273e97c6e49 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -27,8 +27,8 @@ struct GPUBatch;
struct GPUMaterial;
struct ModifierData;
struct Object;
-struct ParticleSystem;
struct PTCacheEdit;
+struct ParticleSystem;
void DRW_shape_cache_free(void);
void DRW_shape_cache_reset(void);
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c
index 95b984747bd..d952965de35 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.c
@@ -454,7 +454,8 @@ static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo))
BMFace *efa;
BM_ITER_MESH (efa, &iter, mr->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
- mat_tri_len[efa->mat_nr] += efa->len - 2;
+ int mat = min_ii(efa->mat_nr, mr->mat_len - 1);
+ mat_tri_len[mat] += efa->len - 2;
}
}
}
@@ -462,7 +463,8 @@ static void *extract_tris_init(const MeshRenderData *mr, void *UNUSED(ibo))
const MPoly *mpoly = mr->mpoly;
for (int p = 0; p < mr->poly_len; p++, mpoly++) {
if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
- mat_tri_len[mpoly->mat_nr] += mpoly->totloop - 2;
+ int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1);
+ mat_tri_len[mat] += mpoly->totloop - 2;
}
}
}
@@ -505,11 +507,12 @@ static void extract_tris_looptri_mesh(const MeshRenderData *mr,
void *_data)
{
const MPoly *mpoly = &mr->mpoly[mlt->poly];
- if (!(mpoly->flag & ME_HIDE)) {
+ if (!(mr->use_hide && (mpoly->flag & ME_HIDE))) {
MeshExtract_Tri_Data *data = _data;
int *mat_tri_ofs = data->tri_mat_end;
+ int mat = min_ii(mpoly->mat_nr, mr->mat_len - 1);
GPU_indexbuf_set_tri_verts(
- &data->elb, mat_tri_ofs[mpoly->mat_nr]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
+ &data->elb, mat_tri_ofs[mat]++, mlt->tri[0], mlt->tri[1], mlt->tri[2]);
}
}
@@ -534,18 +537,20 @@ static void extract_tris_finish(const MeshRenderData *mr, void *ibo, void *_data
MEM_freeN(data);
}
-const MeshExtract extract_tris = {extract_tris_init,
- extract_tris_looptri_bmesh,
- extract_tris_looptri_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_tris_finish,
- 0,
- false};
+static const MeshExtract extract_tris = {
+ extract_tris_init,
+ extract_tris_looptri_bmesh,
+ extract_tris_looptri_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_tris_finish,
+ 0,
+ false,
+};
/** \} */
@@ -645,18 +650,20 @@ static void extract_lines_finish(const MeshRenderData *mr, void *ibo, void *elb)
}
}
-const MeshExtract extract_lines = {extract_lines_init,
- NULL,
- NULL,
- extract_lines_loop_bmesh,
- extract_lines_loop_mesh,
- extract_lines_ledge_bmesh,
- extract_lines_ledge_mesh,
- NULL,
- NULL,
- extract_lines_finish,
- 0,
- false};
+static const MeshExtract extract_lines = {
+ extract_lines_init,
+ NULL,
+ NULL,
+ extract_lines_loop_bmesh,
+ extract_lines_loop_mesh,
+ extract_lines_ledge_bmesh,
+ extract_lines_ledge_mesh,
+ NULL,
+ NULL,
+ extract_lines_finish,
+ 0,
+ false,
+};
/** \} */
@@ -750,18 +757,20 @@ static void extract_points_finish(const MeshRenderData *UNUSED(mr), void *ibo, v
MEM_freeN(elb);
}
-const MeshExtract extract_points = {extract_points_init,
- NULL,
- NULL,
- extract_points_loop_bmesh,
- extract_points_loop_mesh,
- extract_points_ledge_bmesh,
- extract_points_ledge_mesh,
- extract_points_lvert_bmesh,
- extract_points_lvert_mesh,
- extract_points_finish,
- 0,
- false};
+static const MeshExtract extract_points = {
+ extract_points_init,
+ NULL,
+ NULL,
+ extract_points_loop_bmesh,
+ extract_points_loop_mesh,
+ extract_points_ledge_bmesh,
+ extract_points_ledge_mesh,
+ extract_points_lvert_bmesh,
+ extract_points_lvert_mesh,
+ extract_points_finish,
+ 0,
+ false,
+};
/** \} */
@@ -813,18 +822,20 @@ static void extract_fdots_finish(const MeshRenderData *UNUSED(mr), void *ibo, vo
MEM_freeN(elb);
}
-const MeshExtract extract_fdots = {extract_fdots_init,
- NULL,
- NULL,
- extract_fdots_loop_bmesh,
- extract_fdots_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_fdots_finish,
- 0,
- false};
+static const MeshExtract extract_fdots = {
+ extract_fdots_init,
+ NULL,
+ NULL,
+ extract_fdots_loop_bmesh,
+ extract_fdots_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_fdots_finish,
+ 0,
+ false,
+};
/** \} */
@@ -886,18 +897,20 @@ static void extract_lines_paint_mask_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data);
}
-const MeshExtract extract_lines_paint_mask = {extract_lines_paint_mask_init,
- NULL,
- NULL,
- NULL,
- extract_lines_paint_mask_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_lines_paint_mask_finish,
- 0,
- false};
+static const MeshExtract extract_lines_paint_mask = {
+ extract_lines_paint_mask_init,
+ NULL,
+ NULL,
+ NULL,
+ extract_lines_paint_mask_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_lines_paint_mask_finish,
+ 0,
+ false,
+};
/** \} */
@@ -919,7 +932,7 @@ static void *extract_lines_adjacency_init(const MeshRenderData *mr, void *UNUSED
{
/* Similar to poly_to_tri_count().
* There is always loop + tri - 1 edges inside a polygon.
- * Cummulate for all polys and you get : */
+ * Accumulate for all polys and you get : */
uint tess_edge_len = mr->loop_len + mr->tri_len - mr->poly_len;
size_t vert_to_loop_size = sizeof(uint) * mr->vert_len;
@@ -1038,18 +1051,20 @@ static void extract_lines_adjacency_finish(const MeshRenderData *mr, void *ibo,
#undef NO_EDGE
-const MeshExtract extract_lines_adjacency = {extract_lines_adjacency_init,
- extract_lines_adjacency_looptri_bmesh,
- extract_lines_adjacency_looptri_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_lines_adjacency_finish,
- 0,
- false};
+static const MeshExtract extract_lines_adjacency = {
+ extract_lines_adjacency_init,
+ extract_lines_adjacency_looptri_bmesh,
+ extract_lines_adjacency_looptri_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_lines_adjacency_finish,
+ 0,
+ false,
+};
/** \} */
@@ -1112,18 +1127,20 @@ static void extract_edituv_tris_finish(const MeshRenderData *UNUSED(mr), void *i
MEM_freeN(extract_data);
}
-const MeshExtract extract_edituv_tris = {extract_edituv_tris_init,
- extract_edituv_tris_looptri_bmesh,
- extract_edituv_tris_looptri_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_edituv_tris_finish,
- 0,
- false};
+static const MeshExtract extract_edituv_tris = {
+ extract_edituv_tris_init,
+ extract_edituv_tris_looptri_bmesh,
+ extract_edituv_tris_looptri_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_edituv_tris_finish,
+ 0,
+ false,
+};
/** \} */
@@ -1185,18 +1202,20 @@ static void extract_edituv_lines_finish(const MeshRenderData *UNUSED(mr), void *
MEM_freeN(extract_data);
}
-const MeshExtract extract_edituv_lines = {extract_edituv_lines_init,
- NULL,
- NULL,
- extract_edituv_lines_loop_bmesh,
- extract_edituv_lines_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_edituv_lines_finish,
- 0,
- false};
+static const MeshExtract extract_edituv_lines = {
+ extract_edituv_lines_init,
+ NULL,
+ NULL,
+ extract_edituv_lines_loop_bmesh,
+ extract_edituv_lines_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_edituv_lines_finish,
+ 0,
+ false,
+};
/** \} */
@@ -1254,18 +1273,20 @@ static void extract_edituv_points_finish(const MeshRenderData *UNUSED(mr), void
MEM_freeN(extract_data);
}
-const MeshExtract extract_edituv_points = {extract_edituv_points_init,
- NULL,
- NULL,
- extract_edituv_points_loop_bmesh,
- extract_edituv_points_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_edituv_points_finish,
- 0,
- false};
+static const MeshExtract extract_edituv_points = {
+ extract_edituv_points_init,
+ NULL,
+ NULL,
+ extract_edituv_points_loop_bmesh,
+ extract_edituv_points_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_edituv_points_finish,
+ 0,
+ false,
+};
/** \} */
@@ -1330,18 +1351,20 @@ static void extract_edituv_fdots_finish(const MeshRenderData *UNUSED(mr), void *
MEM_freeN(data);
}
-const MeshExtract extract_edituv_fdots = {extract_edituv_fdots_init,
- NULL,
- NULL,
- extract_edituv_fdots_loop_bmesh,
- extract_edituv_fdots_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_edituv_fdots_finish,
- 0,
- false};
+static const MeshExtract extract_edituv_fdots = {
+ extract_edituv_fdots_init,
+ NULL,
+ NULL,
+ extract_edituv_fdots_loop_bmesh,
+ extract_edituv_fdots_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_edituv_fdots_finish,
+ 0,
+ false,
+};
/** \} */
@@ -1410,7 +1433,7 @@ static void extract_pos_nor_loop_mesh(const MeshRenderData *mr,
int l,
const MLoop *mloop,
int UNUSED(p),
- const MPoly *mpoly,
+ const MPoly *UNUSED(mpoly),
void *_data)
{
MeshExtract_PosNor_Data *data = _data;
@@ -1419,12 +1442,15 @@ static void extract_pos_nor_loop_mesh(const MeshRenderData *mr,
copy_v3_v3(vert->pos, mvert->co);
vert->nor = data->packed_nor[mloop->v];
/* Flag for paint mode overlay. */
- if (mpoly->flag & ME_HIDE)
+ if (mvert->flag & ME_HIDE) {
vert->nor.w = -1;
- else if (mpoly->flag & ME_FACE_SEL)
+ }
+ else if (mvert->flag & SELECT) {
vert->nor.w = 1;
- else
+ }
+ else {
vert->nor.w = 0;
+ }
}
static void extract_pos_nor_ledge_bmesh(const MeshRenderData *mr, int e, BMEdge *eed, void *_data)
@@ -1479,18 +1505,20 @@ static void extract_pos_nor_finish(const MeshRenderData *UNUSED(mr), void *UNUSE
MEM_freeN(data);
}
-const MeshExtract extract_pos_nor = {extract_pos_nor_init,
- NULL,
- NULL,
- extract_pos_nor_loop_bmesh,
- extract_pos_nor_loop_mesh,
- extract_pos_nor_ledge_bmesh,
- extract_pos_nor_ledge_mesh,
- extract_pos_nor_lvert_bmesh,
- extract_pos_nor_lvert_mesh,
- extract_pos_nor_finish,
- 0,
- true};
+static const MeshExtract extract_pos_nor = {
+ extract_pos_nor_init,
+ NULL,
+ NULL,
+ extract_pos_nor_loop_bmesh,
+ extract_pos_nor_loop_mesh,
+ extract_pos_nor_ledge_bmesh,
+ extract_pos_nor_ledge_mesh,
+ extract_pos_nor_lvert_bmesh,
+ extract_pos_nor_lvert_mesh,
+ extract_pos_nor_finish,
+ 0,
+ true,
+};
/** \} */
/* ---------------------------------------------------------------------- */
@@ -1501,7 +1529,7 @@ static void *extract_lnor_init(const MeshRenderData *mr, void *buf)
{
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
- GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I10, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
GPU_vertformat_alias_add(&format, "lnor");
}
GPUVertBuf *vbo = buf;
@@ -1536,20 +1564,32 @@ static void extract_lnor_loop_mesh(
else {
((GPUPackedNormal *)data)[l] = GPU_normal_convert_i10_v3(mr->poly_normals[p]);
}
-}
-
-const MeshExtract extract_lnor = {extract_lnor_init,
- NULL,
- NULL,
- extract_lnor_loop_bmesh,
- extract_lnor_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- MR_DATA_LOOP_NOR,
- true};
+ /* Flag for paint mode overlay. */
+ if (mpoly->flag & ME_HIDE) {
+ ((GPUPackedNormal *)data)[l].w = -1;
+ }
+ else if (mpoly->flag & ME_FACE_SEL) {
+ ((GPUPackedNormal *)data)[l].w = 1;
+ }
+ else {
+ ((GPUPackedNormal *)data)[l].w = 0;
+ }
+}
+
+static const MeshExtract extract_lnor = {
+ extract_lnor_init,
+ NULL,
+ NULL,
+ extract_lnor_loop_bmesh,
+ extract_lnor_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ MR_DATA_LOOP_NOR,
+ true,
+};
/** \} */
@@ -1633,8 +1673,21 @@ static void *extract_uv_init(const MeshRenderData *mr, void *buf)
return NULL;
}
-const MeshExtract extract_uv = {
- extract_uv_init, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, false};
+static const MeshExtract extract_uv = {
+ extract_uv_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ false,
+};
+
/** \} */
/* ---------------------------------------------------------------------- */
@@ -1775,18 +1828,20 @@ static void *extract_tan_init(const MeshRenderData *mr, void *buf)
return NULL;
}
-const MeshExtract extract_tan = {extract_tan_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
- false};
+static const MeshExtract extract_tan = {
+ extract_tan_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ MR_DATA_POLY_NOR | MR_DATA_TAN_LOOP_NOR | MR_DATA_LOOPTRI,
+ false,
+};
/** \} */
@@ -1840,10 +1895,21 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
return NULL;
}
-const MeshExtract extract_vcol = {
- extract_vcol_init, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, false};
+static const MeshExtract extract_vcol = {
+ extract_vcol_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ false,
+};
-/** \} */ /** \} */
+/** \} */
/* ---------------------------------------------------------------------- */
/** \name Extract Orco
@@ -1859,8 +1925,8 @@ static void *extract_orco_init(const MeshRenderData *mr, void *buf)
static GPUVertFormat format = {0};
if (format.attr_len == 0) {
/* FIXME(fclem): We use the last component as a way to differentiate from generic vertex
- * attribs. This is a substential waste of Vram and should be done another way.
- * Unfortunately, at the time of writting, I did not found any other "non disruptive"
+ * attribs. This is a substantial waste of Vram and should be done another way.
+ * Unfortunately, at the time of writing, I did not found any other "non disruptive"
* alternative. */
GPU_vertformat_attr_add(&format, "orco", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
}
@@ -1908,18 +1974,20 @@ static void extract_orco_finish(const MeshRenderData *UNUSED(mr), void *UNUSED(b
MEM_freeN(data);
}
-const MeshExtract extract_orco = {extract_orco_init,
- NULL,
- NULL,
- extract_orco_loop_bmesh,
- extract_orco_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_orco_finish,
- 0,
- true};
+static const MeshExtract extract_orco = {
+ extract_orco_init,
+ NULL,
+ NULL,
+ extract_orco_loop_bmesh,
+ extract_orco_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_orco_finish,
+ 0,
+ true,
+};
/** \} */
@@ -2085,18 +2153,20 @@ static void extract_edge_fac_finish(const MeshRenderData *mr, void *buf, void *_
MEM_freeN(data);
}
-const MeshExtract extract_edge_fac = {extract_edge_fac_init,
- NULL,
- NULL,
- extract_edge_fac_loop_bmesh,
- extract_edge_fac_loop_mesh,
- extract_edge_fac_ledge_bmesh,
- extract_edge_fac_ledge_mesh,
- NULL,
- NULL,
- extract_edge_fac_finish,
- MR_DATA_POLY_NOR,
- false};
+static const MeshExtract extract_edge_fac = {
+ extract_edge_fac_init,
+ NULL,
+ NULL,
+ extract_edge_fac_loop_bmesh,
+ extract_edge_fac_loop_mesh,
+ extract_edge_fac_ledge_bmesh,
+ extract_edge_fac_ledge_mesh,
+ NULL,
+ NULL,
+ extract_edge_fac_finish,
+ MR_DATA_POLY_NOR,
+ false,
+};
/** \} */
/* ---------------------------------------------------------------------- */
@@ -2213,18 +2283,20 @@ static void extract_weights_finish(const MeshRenderData *UNUSED(mr), void *UNUSE
MEM_freeN(data);
}
-const MeshExtract extract_weights = {extract_weights_init,
- NULL,
- NULL,
- extract_weights_loop_bmesh,
- extract_weights_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_weights_finish,
- 0,
- true};
+static const MeshExtract extract_weights = {
+ extract_weights_init,
+ NULL,
+ NULL,
+ extract_weights_loop_bmesh,
+ extract_weights_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_weights_finish,
+ 0,
+ true,
+};
/** \} */
@@ -2479,18 +2551,20 @@ static void extract_edit_data_lvert_mesh(const MeshRenderData *mr,
}
}
-const MeshExtract extract_edit_data = {extract_edit_data_init,
- NULL,
- NULL,
- extract_edit_data_loop_bmesh,
- extract_edit_data_loop_mesh,
- extract_edit_data_ledge_bmesh,
- extract_edit_data_ledge_mesh,
- extract_edit_data_lvert_bmesh,
- extract_edit_data_lvert_mesh,
- NULL,
- 0,
- true};
+static const MeshExtract extract_edit_data = {
+ extract_edit_data_init,
+ NULL,
+ NULL,
+ extract_edit_data_loop_bmesh,
+ extract_edit_data_loop_mesh,
+ extract_edit_data_ledge_bmesh,
+ extract_edit_data_ledge_mesh,
+ extract_edit_data_lvert_bmesh,
+ extract_edit_data_lvert_mesh,
+ NULL,
+ 0,
+ true,
+};
/** \} */
@@ -2516,7 +2590,7 @@ static void *extract_edituv_data_init(const MeshRenderData *mr, void *buf)
GPU_vertbuf_init_with_format(vbo, &format);
GPU_vertbuf_data_alloc(vbo, mr->loop_len);
- CustomData *cd_ldata = &mr->me->ldata;
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
MeshExtract_EditUVData_Data *data = MEM_callocN(sizeof(*data), __func__);
data->vbo_data = (EditLoopData *)vbo->data;
@@ -2577,18 +2651,20 @@ static void extract_edituv_data_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data);
}
-const MeshExtract extract_edituv_data = {extract_edituv_data_init,
- NULL,
- NULL,
- extract_edituv_data_loop_bmesh,
- extract_edituv_data_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_edituv_data_finish,
- 0,
- true};
+static const MeshExtract extract_edituv_data = {
+ extract_edituv_data_init,
+ NULL,
+ NULL,
+ extract_edituv_data_loop_bmesh,
+ extract_edituv_data_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_edituv_data_finish,
+ 0,
+ true,
+};
/** \} */
@@ -2708,18 +2784,20 @@ static void mesh_stretch_area_finish(const MeshRenderData *mr, void *buf, void *
MEM_freeN(area_ratio);
}
-const MeshExtract extract_stretch_area = {extract_stretch_area_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- mesh_stretch_area_finish,
- 0,
- false};
+static const MeshExtract extract_stretch_area = {
+ extract_stretch_area_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ mesh_stretch_area_finish,
+ 0,
+ false,
+};
/** \} */
@@ -2744,8 +2822,8 @@ static void compute_normalize_edge_vectors(float auv[2][2],
float av[2][3],
const float uv[2],
const float uv_prev[2],
- const float co[2],
- const float co_prev[2])
+ const float co[3],
+ const float co_prev[3])
{
/* Move previous edge. */
copy_v2_v2(auv[0], auv[1]);
@@ -2896,18 +2974,20 @@ static void extract_stretch_angle_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data);
}
-const MeshExtract extract_stretch_angle = {extract_stretch_angle_init,
- NULL,
- NULL,
- extract_stretch_angle_loop_bmesh,
- extract_stretch_angle_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_stretch_angle_finish,
- 0,
- true};
+static const MeshExtract extract_stretch_angle = {
+ extract_stretch_angle_init,
+ NULL,
+ NULL,
+ extract_stretch_angle_loop_bmesh,
+ extract_stretch_angle_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_stretch_angle_finish,
+ 0,
+ false,
+};
/** \} */
@@ -3479,20 +3559,22 @@ static void extract_mesh_analysis_finish(const MeshRenderData *mr, void *buf, vo
}
}
-const MeshExtract extract_mesh_analysis = {extract_mesh_analysis_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_mesh_analysis_finish,
- /* This is not needed for all vis type.
- * Maybe split into different extract. */
- MR_DATA_POLY_NOR | MR_DATA_LOOPTRI,
- false};
+static const MeshExtract extract_mesh_analysis = {
+ extract_mesh_analysis_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_mesh_analysis_finish,
+ /* This is not needed for all vis type.
+ * Maybe split into different extract. */
+ MR_DATA_POLY_NOR | MR_DATA_LOOPTRI,
+ false,
+};
/** \} */
@@ -3546,18 +3628,20 @@ static void extract_fdots_pos_loop_mesh(const MeshRenderData *mr,
}
}
-const MeshExtract extract_fdots_pos = {extract_fdots_pos_init,
- NULL,
- NULL,
- extract_fdots_pos_loop_bmesh,
- extract_fdots_pos_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- true};
+static const MeshExtract extract_fdots_pos = {
+ extract_fdots_pos_init,
+ NULL,
+ NULL,
+ extract_fdots_pos_loop_bmesh,
+ extract_fdots_pos_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ true,
+};
/** \} */
@@ -3604,18 +3688,20 @@ static void extract_fdots_nor_finish(const MeshRenderData *mr, void *buf, void *
}
}
-const MeshExtract extract_fdots_nor = {extract_fdots_nor_init,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_fdots_nor_finish,
- MR_DATA_POLY_NOR,
- false};
+static const MeshExtract extract_fdots_nor = {
+ extract_fdots_nor_init,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_fdots_nor_finish,
+ MR_DATA_POLY_NOR,
+ false,
+};
/** \} */
@@ -3686,18 +3772,20 @@ static void extract_fdots_uv_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data);
}
-const MeshExtract extract_fdots_uv = {extract_fdots_uv_init,
- NULL,
- NULL,
- extract_fdots_uv_loop_bmesh,
- extract_fdots_uv_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_fdots_uv_finish,
- 0,
- true};
+static const MeshExtract extract_fdots_uv = {
+ extract_fdots_uv_init,
+ NULL,
+ NULL,
+ extract_fdots_uv_loop_bmesh,
+ extract_fdots_uv_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_fdots_uv_finish,
+ 0,
+ true,
+};
/** \} */
/* ---------------------------------------------------------------------- */
@@ -3759,18 +3847,20 @@ static void extract_fdots_edituv_data_finish(const MeshRenderData *UNUSED(mr),
MEM_freeN(data);
}
-const MeshExtract extract_fdots_edituv_data = {extract_fdots_edituv_data_init,
- NULL,
- NULL,
- extract_fdots_edituv_data_loop_bmesh,
- extract_fdots_edituv_data_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- extract_fdots_edituv_data_finish,
- 0,
- true};
+static const MeshExtract extract_fdots_edituv_data = {
+ extract_fdots_edituv_data_init,
+ NULL,
+ NULL,
+ extract_fdots_edituv_data_loop_bmesh,
+ extract_fdots_edituv_data_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ extract_fdots_edituv_data_finish,
+ 0,
+ true,
+};
/** \} */
/* ---------------------------------------------------------------------- */
@@ -3790,7 +3880,7 @@ static void *extract_select_idx_init(const MeshRenderData *mr, void *buf)
return vbo->data;
}
-/* TODO Use glVertexID to get loop index and use the data structure on the CPU to retreive the
+/* TODO Use glVertexID to get loop index and use the data structure on the CPU to retrieve the
* select element associated with this loop ID. This would remove the need for this separate index
* VBOs. We could upload the p/e/v_origindex as a buffer texture and sample it inside the shader to
* output original index. */
@@ -3898,44 +3988,50 @@ static void extract_vert_idx_lvert_mesh(const MeshRenderData *mr,
((uint32_t *)data)[mr->loop_len + mr->edge_loose_len * 2 + v] = v_orig;
}
-const MeshExtract extract_poly_idx = {extract_select_idx_init,
- NULL,
- NULL,
- extract_poly_idx_loop_bmesh,
- extract_poly_idx_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- true};
-
-const MeshExtract extract_edge_idx = {extract_select_idx_init,
- NULL,
- NULL,
- extract_edge_idx_loop_bmesh,
- extract_edge_idx_loop_mesh,
- extract_edge_idx_ledge_bmesh,
- extract_edge_idx_ledge_mesh,
- NULL,
- NULL,
- NULL,
- 0,
- true};
-
-const MeshExtract extract_vert_idx = {extract_select_idx_init,
- NULL,
- NULL,
- extract_vert_idx_loop_bmesh,
- extract_vert_idx_loop_mesh,
- extract_vert_idx_ledge_bmesh,
- extract_vert_idx_ledge_mesh,
- extract_vert_idx_lvert_bmesh,
- extract_vert_idx_lvert_mesh,
- NULL,
- 0,
- true};
+static const MeshExtract extract_poly_idx = {
+ extract_select_idx_init,
+ NULL,
+ NULL,
+ extract_poly_idx_loop_bmesh,
+ extract_poly_idx_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ true,
+};
+
+static const MeshExtract extract_edge_idx = {
+ extract_select_idx_init,
+ NULL,
+ NULL,
+ extract_edge_idx_loop_bmesh,
+ extract_edge_idx_loop_mesh,
+ extract_edge_idx_ledge_bmesh,
+ extract_edge_idx_ledge_mesh,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ true,
+};
+
+static const MeshExtract extract_vert_idx = {
+ extract_select_idx_init,
+ NULL,
+ NULL,
+ extract_vert_idx_loop_bmesh,
+ extract_vert_idx_loop_mesh,
+ extract_vert_idx_ledge_bmesh,
+ extract_vert_idx_ledge_mesh,
+ extract_vert_idx_lvert_bmesh,
+ extract_vert_idx_lvert_mesh,
+ NULL,
+ 0,
+ true,
+};
static void *extract_select_fdot_idx_init(const MeshRenderData *mr, void *buf)
{
@@ -3968,18 +4064,20 @@ static void extract_fdot_idx_loop_mesh(const MeshRenderData *mr,
((uint32_t *)data)[p] = (mr->p_origindex) ? mr->p_origindex[p] : p;
}
-const MeshExtract extract_fdot_idx = {extract_select_fdot_idx_init,
- NULL,
- NULL,
- extract_fdot_idx_loop_bmesh,
- extract_fdot_idx_loop_mesh,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- true};
+static const MeshExtract extract_fdot_idx = {
+ extract_select_fdot_idx_init,
+ NULL,
+ NULL,
+ extract_fdot_idx_loop_bmesh,
+ extract_fdot_idx_loop_mesh,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ true,
+};
/** \} */
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index d392db63938..3e33346c7d8 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -23,18 +23,14 @@
#ifndef __DRAW_CACHE_IMPL_H__
#define __DRAW_CACHE_IMPL_H__
-struct CurveCache;
struct GPUBatch;
struct GPUIndexBuf;
struct GPUMaterial;
-struct GPUTexture;
struct GPUVertBuf;
struct ListBase;
struct ModifierData;
struct PTCacheEdit;
struct ParticleSystem;
-struct SpaceImage;
-struct ToolSettings;
struct Curve;
struct Lattice;
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index 90bbf996851..eef108b1f2f 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -66,7 +66,7 @@ static int dl_tri_len(const DispList *dl)
return 0;
}
-/* see: displist_get_allverts */
+/* see: displist_vert_coords_alloc */
static int curve_render_surface_vert_len_get(const ListBase *lb)
{
int vert_len = 0;
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 12c6a715685..456e21db6ed 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -549,6 +549,7 @@ void DRW_mesh_batch_cache_dirty_tag(Mesh *me, int mode)
{
GPU_INDEXBUF_DISCARD_SAFE(mbufcache->ibo.lines_paint_mask);
GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.pos_nor);
+ GPU_VERTBUF_DISCARD_SAFE(mbufcache->vbo.lnor);
}
GPU_BATCH_DISCARD_SAFE(cache->batch.surface);
GPU_BATCH_DISCARD_SAFE(cache->batch.wire_loops);
@@ -969,6 +970,7 @@ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime)
void DRW_mesh_batch_cache_create_requested(
Object *ob, Mesh *me, const Scene *scene, const bool is_paint_mode, const bool use_hide)
{
+ GPUIndexBuf **saved_elem_ranges = NULL;
const ToolSettings *ts = NULL;
if (scene) {
ts = scene->toolsettings;
@@ -1031,6 +1033,17 @@ void DRW_mesh_batch_cache_create_requested(
GPU_VERTBUF_DISCARD_SAFE(mbuffercache->vbo.vcol);
}
}
+ /* XXX save element buffer to avoid recreating them.
+ * This is only if the cd_needed changes so it is ok to keep them.*/
+ if (cache->surface_per_mat[0] && cache->surface_per_mat[0]->elem) {
+ saved_elem_ranges = MEM_callocN(sizeof(saved_elem_ranges) * cache->mat_len, __func__);
+ for (int i = 0; i < cache->mat_len; ++i) {
+ saved_elem_ranges[i] = cache->surface_per_mat[i]->elem;
+ /* Avoid deletion as the batch is owner. */
+ cache->surface_per_mat[i]->elem = NULL;
+ cache->surface_per_mat[i]->owns_flag &= ~GPU_BATCH_OWNS_INDEX;
+ }
+ }
/* We can't discard batches at this point as they have been
* referenced for drawing. Just clear them in place. */
for (int i = 0; i < cache->mat_len; ++i) {
@@ -1128,6 +1141,8 @@ void DRW_mesh_batch_cache_create_requested(
}
if (DRW_batch_requested(cache->batch.wire_loops, GPU_PRIM_LINES)) {
DRW_ibo_request(cache->batch.wire_loops, &mbufcache->ibo.lines_paint_mask);
+ /* Order matters. First ones override latest vbos' attribs. */
+ DRW_vbo_request(cache->batch.wire_loops, &mbufcache->vbo.lnor);
DRW_vbo_request(cache->batch.wire_loops, &mbufcache->vbo.pos_nor);
}
if (DRW_batch_requested(cache->batch.wire_edges, GPU_PRIM_LINES)) {
@@ -1151,7 +1166,13 @@ void DRW_mesh_batch_cache_create_requested(
/* Per Material */
for (int i = 0; i < cache->mat_len; ++i) {
if (DRW_batch_requested(cache->surface_per_mat[i], GPU_PRIM_TRIS)) {
- DRW_ibo_request(cache->surface_per_mat[i], &mbufcache->ibo.tris);
+ if (saved_elem_ranges && saved_elem_ranges[i]) {
+ /* XXX assign old element buffer range (it did not change).*/
+ GPU_batch_elembuf_set(cache->surface_per_mat[i], saved_elem_ranges[i], true);
+ }
+ else {
+ DRW_ibo_request(cache->surface_per_mat[i], &mbufcache->ibo.tris);
+ }
/* Order matters. First ones override latest vbos' attribs. */
DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.lnor);
DRW_vbo_request(cache->surface_per_mat[i], &mbufcache->vbo.pos_nor);
@@ -1170,6 +1191,8 @@ void DRW_mesh_batch_cache_create_requested(
}
}
+ MEM_SAFE_FREE(saved_elem_ranges);
+
mbufcache = (do_cage) ? &cache->cage : &cache->final;
/* Edit Mesh */
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c
index e3867eef8d8..2f4a08d4525 100644
--- a/source/blender/draw/intern/draw_common.c
+++ b/source/blender/draw/intern/draw_common.c
@@ -243,6 +243,7 @@ extern char datatoc_gpu_shader_point_varying_color_frag_glsl[];
extern char datatoc_object_mball_handles_vert_glsl[];
extern char datatoc_object_empty_axes_vert_glsl[];
+extern char datatoc_object_color_axes_vert_glsl[];
typedef struct COMMON_Shaders {
struct GPUShader *shape_outline;
@@ -262,6 +263,7 @@ typedef struct COMMON_Shaders {
struct GPUShader *volume_velocity_needle_sh;
struct GPUShader *volume_velocity_sh;
struct GPUShader *empty_axes_sh;
+ struct GPUShader *color_axes_sh;
struct GPUShader *mball_handles;
} COMMON_Shaders;
@@ -549,6 +551,37 @@ struct DRWCallBuffer *buffer_instance_empty_axes(DRWPass *pass,
return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom);
}
+struct DRWCallBuffer *buffer_instance_color_axes(DRWPass *pass,
+ struct GPUBatch *geom,
+ DRWShadingGroup **r_grp,
+ eGPUShaderConfig sh_cfg)
+{
+ COMMON_Shaders *sh_data = &g_shaders[sh_cfg];
+ if (sh_data->color_axes_sh == NULL) {
+ const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
+ sh_data->color_axes_sh = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg_data->lib, datatoc_object_color_axes_vert_glsl, NULL},
+ .frag = (const char *[]){datatoc_gpu_shader_flat_color_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg_data->def, NULL},
+ });
+ }
+
+ DRW_shgroup_instance_format(g_formats.instance_sized,
+ {
+ {"color", DRW_ATTR_FLOAT, 3},
+ {"size", DRW_ATTR_FLOAT, 1},
+ {"InstanceModelMatrix", DRW_ATTR_FLOAT, 16},
+ });
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh_data->color_axes_sh, pass);
+ DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2);
+ if (sh_cfg == GPU_SHADER_CFG_CLIPPED) {
+ DRW_shgroup_state_enable(grp, DRW_STATE_CLIP_PLANES);
+ }
+ *r_grp = grp;
+ return DRW_shgroup_call_buffer_instance(grp, g_formats.instance_sized, geom);
+}
+
struct DRWCallBuffer *buffer_instance_outline(DRWPass *pass,
struct GPUBatch *geom,
const int *baseid,
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 05d7bafa00d..9899b6c0194 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -30,7 +30,6 @@ struct GPUBatch;
struct GPUMaterial;
struct ModifierData;
struct Object;
-struct PTCacheEdit;
struct ParticleSystem;
struct ViewLayer;
@@ -113,7 +112,6 @@ typedef struct GlobalsUboStorage {
/* Pack individual float at the end of the buffer to avoid alignment errors */
float sizeLightCenter, sizeLightCircle, sizeLightCircleShadow;
float sizeVertex, sizeEdge, sizeEdgeFix, sizeFaceDot;
- float gridDistance, gridResolution, gridSubdivisions, gridScale;
float pad_globalsBlock;
} GlobalsUboStorage;
@@ -162,6 +160,10 @@ struct DRWCallBuffer *buffer_instance_screen_aligned(struct DRWPass *pass,
struct DRWCallBuffer *buffer_instance_empty_axes(struct DRWPass *pass,
struct GPUBatch *geom,
eGPUShaderConfig sh_cfg);
+struct DRWCallBuffer *buffer_instance_color_axes(struct DRWPass *pass,
+ struct GPUBatch *geom,
+ struct DRWShadingGroup **r_grp,
+ eGPUShaderConfig sh_cfg);
struct DRWCallBuffer *buffer_instance_scaled(struct DRWPass *pass,
struct GPUBatch *geom,
eGPUShaderConfig sh_cfg);
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index fa1f1f2aab4..44ed01c47aa 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -253,7 +253,7 @@ void DRW_hair_update(void)
* On some system it crashes (see T58489) and on some other it renders garbage (see T60171).
*
* So instead of using transform feedback we render to a texture,
- * readback the result to system memory and reupload as VBO data.
+ * read back the result to system memory and re-upload as VBO data.
* It is really not ideal performance wise, but it is the simplest
* and the most local workaround that still uses the power of the GPU.
*/
diff --git a/source/blender/draw/intern/draw_instance_data.c b/source/blender/draw/intern/draw_instance_data.c
index 802f49d6549..8f26cc72a02 100644
--- a/source/blender/draw/intern/draw_instance_data.c
+++ b/source/blender/draw/intern/draw_instance_data.c
@@ -23,7 +23,7 @@
/**
* DRW Instance Data Manager
* This is a special memory manager that keeps memory blocks ready to send as vbo data in one
- * continuous allocation. This way we avoid feeding gawain each instance data one by one and
+ * continuous allocation. This way we avoid feeding #GPUBatch each instance data one by one and
* unnecessary memcpy. Since we loose which memory block was used each #DRWShadingGroup we need to
* redistribute them in the same order/size to avoid to realloc each frame. This is why
* #DRWInstanceDatas are sorted in a list for each different data size.
diff --git a/source/blender/draw/intern/draw_instance_data.h b/source/blender/draw/intern/draw_instance_data.h
index d88de1a58e2..2ede68e16d8 100644
--- a/source/blender/draw/intern/draw_instance_data.h
+++ b/source/blender/draw/intern/draw_instance_data.h
@@ -35,8 +35,6 @@
typedef struct DRWInstanceData DRWInstanceData;
typedef struct DRWInstanceDataList DRWInstanceDataList;
-struct DRWShadingGroup;
-
void *DRW_instance_data_next(DRWInstanceData *idata);
DRWInstanceData *DRW_instance_data_request(DRWInstanceDataList *idatalist, uint attr_size);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index ebbe3694df8..d88629e9bb7 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -33,6 +33,7 @@
#include "BKE_anim.h"
#include "BKE_colortools.h"
+#include "BKE_context.h"
#include "BKE_curve.h"
#include "BKE_editmesh.h"
#include "BKE_global.h"
@@ -41,6 +42,7 @@
#include "BKE_main.h"
#include "BKE_mball.h"
#include "BKE_mesh.h"
+#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_paint.h"
@@ -604,6 +606,7 @@ static DRWCallState *draw_unit_state_create(void)
state->ob_index = 0;
state->ob_random = 0.0f;
+ copy_v3_fl(state->ob_color, 1.0f);
/* TODO(fclem) get rid of this. */
state->culling = BLI_memblock_alloc(DST.vmempool->cullstates);
@@ -1865,7 +1868,7 @@ void DRW_render_gpencil(struct RenderEngine *engine, struct Depsgraph *depsgraph
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);
+ DRW_gpu_render_context_enable(re_gpu_context);
}
else {
DRW_opengl_context_enable();
@@ -1950,13 +1953,13 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
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);
+ DRW_gpu_render_context_enable(re_gpu_context);
}
else {
DRW_opengl_context_enable();
}
- /* IMPORTANT: We dont support immediate mode in render mode!
+ /* IMPORTANT: We don't support immediate mode in render mode!
* This shall remain in effect until immediate mode supports
* multiple threads. */
@@ -2041,7 +2044,7 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
/* Changing Context */
if (re_gl_context != NULL) {
- DRW_gawain_render_context_disable(re_gpu_context);
+ DRW_gpu_render_context_disable(re_gpu_context);
DRW_opengl_render_context_disable(re_gl_context);
}
else {
@@ -2204,24 +2207,43 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
drw_state_prepare_clean_for_draw(&DST);
bool use_obedit = false;
- int obedit_mode = 0;
+ /* obedit_ctx_mode is used for selecting the right draw engines */
+ eContextObjectMode obedit_ctx_mode;
+ /* object_mode is used for filtering objects in the depsgraph */
+ eObjectMode object_mode;
+ int object_type = 0;
if (obedit != NULL) {
+ object_type = obedit->type;
+ object_mode = obedit->mode;
if (obedit->type == OB_MBALL) {
use_obedit = true;
- obedit_mode = CTX_MODE_EDIT_METABALL;
+ obedit_ctx_mode = CTX_MODE_EDIT_METABALL;
}
else if (obedit->type == OB_ARMATURE) {
use_obedit = true;
- obedit_mode = CTX_MODE_EDIT_ARMATURE;
+ obedit_ctx_mode = CTX_MODE_EDIT_ARMATURE;
}
}
if (v3d->overlay.flag & V3D_OVERLAY_BONE_SELECT) {
if (!(v3d->flag2 & V3D_HIDE_OVERLAYS)) {
/* Note: don't use "BKE_object_pose_armature_get" here, it breaks selection. */
Object *obpose = OBPOSE_FROM_OBACT(obact);
+ if (obpose == NULL) {
+ Object *obweight = OBWEIGHTPAINT_FROM_OBACT(obact);
+ if (obweight) {
+ /* Only use Armature pose selection, when connected armature is in pose mode. */
+ Object *ob_armature = modifiers_isDeformedByArmature(obweight);
+ if (ob_armature && ob_armature->mode == OB_MODE_POSE) {
+ obpose = ob_armature;
+ }
+ }
+ }
+
if (obpose) {
use_obedit = true;
- obedit_mode = CTX_MODE_POSE;
+ object_type = obpose->type;
+ object_mode = obpose->mode;
+ obedit_ctx_mode = CTX_MODE_POSE;
}
}
}
@@ -2235,8 +2257,8 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
/* Get list of enabled engines */
if (use_obedit) {
- drw_engines_enable_from_paint_mode(obedit_mode);
- drw_engines_enable_from_mode(obedit_mode);
+ drw_engines_enable_from_paint_mode(obedit_ctx_mode);
+ drw_engines_enable_from_mode(obedit_ctx_mode);
}
else if (!draw_surface) {
/* grease pencil selection */
@@ -2283,7 +2305,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
drw_engines_world_update(scene);
if (use_obedit) {
- FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, obact->type, obact->mode, ob_iter) {
+ FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, v3d, object_type, object_mode, ob_iter) {
drw_engines_cache_populate(ob_iter);
}
FOREACH_OBJECT_IN_MODE_END;
@@ -2563,7 +2585,6 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const rc
/* Reset before using it. */
drw_state_prepare_clean_for_draw(&DST);
- DST.buffer_finish_called = true;
/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
DST.draw_ctx = (DRWContextState){
@@ -2601,6 +2622,8 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const rc
}
drw_engines_cache_finish();
+
+ DRW_render_instance_buffer_finish();
}
/* Start Drawing */
@@ -2610,6 +2633,8 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *ar, View3D *v3d, const rc
drw_engines_disable();
+ drw_viewport_cache_resize();
+
#ifdef DEBUG
/* Avoid accidental reuse. */
drw_state_ensure_not_reused(&DST);
@@ -2923,7 +2948,7 @@ 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. */
+ /* Be sure to create gpu_context too. */
DST.gpu_context = GPU_context_create(0);
if (!G.background) {
immActivate();
@@ -3022,7 +3047,7 @@ 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_gpu_context)
+void DRW_gpu_render_context_enable(void *re_gpu_context)
{
/* If thread is main you should use DRW_opengl_context_enable(). */
BLI_assert(!BLI_thread_is_main());
@@ -3032,7 +3057,7 @@ void DRW_gawain_render_context_enable(void *re_gpu_context)
}
/* Needs to be called BEFORE DRW_opengl_render_context_disable() */
-void DRW_gawain_render_context_disable(void *UNUSED(re_gpu_context))
+void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context))
{
DRW_shape_cache_reset(); /* XXX fix that too. */
GPU_context_active_set(NULL);
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index f37e713e374..85f6cf05e83 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -101,6 +101,7 @@ enum {
DRW_CALL_MODELVIEWPROJECTION = (1 << 1),
DRW_CALL_ORCOTEXFAC = (1 << 2),
DRW_CALL_OBJECTINFO = (1 << 3),
+ DRW_CALL_OBJECTCOLOR = (1 << 4),
};
typedef struct DRWCullingState {
@@ -122,6 +123,7 @@ typedef struct DRWCallState {
float modelinverse[4][4];
float orcotexfac[2][3];
float ob_random;
+ float ob_color[4];
} DRWCallState;
typedef struct DRWCall {
@@ -196,6 +198,7 @@ struct DRWShadingGroup {
int orcotexfac;
int callid;
int objectinfo;
+ int objectcolor;
uchar matflag; /* Matrices needed, same as DRWCall.flag */
DRWPass *pass_parent; /* backlink to pass we're in */
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 99ab25645d2..8b7cb9c1dad 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -387,6 +387,10 @@ static void drw_call_state_update_matflag(DRWCallState *state,
}
state->ob_random = random * (1.0f / (float)0xFFFFFFFF);
}
+
+ if (new_flags & DRW_CALL_OBJECTCOLOR) {
+ copy_v4_v4(state->ob_color, ob->color);
+ }
}
static DRWCallState *drw_call_state_create(DRWShadingGroup *shgroup, float (*obmat)[4], Object *ob)
@@ -836,6 +840,7 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
shgroup->modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP);
shgroup->orcotexfac = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_ORCO);
shgroup->objectinfo = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_OBJECT_INFO);
+ shgroup->objectcolor = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_OBJECT_COLOR);
shgroup->callid = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CALLID);
shgroup->matflag = 0;
@@ -851,6 +856,9 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
if (shgroup->objectinfo > -1) {
shgroup->matflag |= DRW_CALL_OBJECTINFO;
}
+ if (shgroup->objectcolor > -1) {
+ shgroup->matflag |= DRW_CALL_OBJECTCOLOR;
+ }
}
static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass)
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 3bf442b4f39..50408015fbc 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -592,6 +592,10 @@ static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call)
infos[3] = (state->flag & DRW_CALL_NEGSCALE) ? -1.0f : 1.0f;
GPU_shader_uniform_vector(shgroup->shader, shgroup->objectinfo, 4, 1, (float *)infos);
}
+ if (shgroup->objectcolor != -1) {
+ GPU_shader_uniform_vector(
+ shgroup->shader, shgroup->objectcolor, 4, 1, (float *)state->ob_color);
+ }
if (shgroup->orcotexfac != -1) {
GPU_shader_uniform_vector(
shgroup->shader, shgroup->orcotexfac, 3, 2, (float *)state->orcotexfac);
@@ -622,12 +626,12 @@ BLI_INLINE void draw_geometry_execute(DRWShadingGroup *shgroup,
GPU_batch_bind(geom);
}
- /* XXX hacking gawain. we don't want to call glUseProgram! (huge performance loss) */
+ /* XXX hacking #GPUBatch. we don't want to call glUseProgram! (huge performance loss) */
geom->program_in_use = true;
GPU_batch_draw_advanced(geom, vert_first, vert_count, inst_first, inst_count);
- geom->program_in_use = false; /* XXX hacking gawain */
+ geom->program_in_use = false; /* XXX hacking #GPUBatch */
}
enum {
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index d0aa6d55c03..9c34cdbac3b 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -178,7 +178,7 @@ static void drw_deferred_shader_compilation_free(void *custom_data)
static void drw_deferred_shader_add(GPUMaterial *mat, bool deferred)
{
- /* Do not deferre the compilation if we are rendering for image.
+ /* Do not defer the compilation if we are rendering for image.
* deferred rendering is only possible when `evil_C` is available */
if (DST.draw_ctx.evil_C == NULL || DRW_state_is_image_render() || !USE_DEFERRED_COMPILATION ||
!deferred) {
diff --git a/source/blender/draw/intern/draw_select_buffer.c b/source/blender/draw/intern/draw_select_buffer.c
index 974ea22ccea..6454fc71e56 100644
--- a/source/blender/draw/intern/draw_select_buffer.c
+++ b/source/blender/draw/intern/draw_select_buffer.c
@@ -75,14 +75,15 @@ uint *DRW_select_buffer_read(struct Depsgraph *depsgraph,
DRW_draw_select_id(depsgraph, ar, v3d, rect);
if (select_ctx->index_drawn_len > 1) {
- BLI_assert(ar->winx == GPU_texture_width(select_ctx->texture_u32) &&
- ar->winy == GPU_texture_height(select_ctx->texture_u32));
+ BLI_assert(ar->winx == GPU_texture_width(DRW_engine_select_texture_get()) &&
+ ar->winy == GPU_texture_height(DRW_engine_select_texture_get()));
/* Read the UI32 pixels. */
buf_len = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect);
r_buf = MEM_mallocN(buf_len * sizeof(*r_buf), __func__);
- GPU_framebuffer_bind(select_ctx->framebuffer_select_id);
+ GPUFrameBuffer *select_id_fb = DRW_engine_select_framebuffer_get();
+ GPU_framebuffer_bind(select_id_fb);
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(rect_clamp.xmin,
rect_clamp.ymin,
diff --git a/source/blender/draw/modes/object_mode.c b/source/blender/draw/modes/object_mode.c
index 87fc74f1f72..716372560db 100644
--- a/source/blender/draw/modes/object_mode.c
+++ b/source/blender/draw/modes/object_mode.c
@@ -234,6 +234,7 @@ typedef struct OBJECT_ShadingGroupList {
/* Helpers */
DRWCallBuffer *relationship_lines;
DRWCallBuffer *constraint_lines;
+ DRWCallBuffer *origin_xform;
/* Camera */
DRWCallBuffer *camera;
@@ -332,7 +333,7 @@ static struct {
OBJECT_Shaders sh_data[GPU_SHADER_CFG_LEN];
- float grid_settings[5];
+ float grid_distance;
float grid_mesh_size;
int grid_flag;
float grid_axes[3];
@@ -340,6 +341,7 @@ static struct {
int zneg_flag;
float zplane_axes[3];
float inv_viewport_size[2];
+ float grid_steps[8];
bool draw_grid;
/* Temp buffer textures */
struct GPUTexture *outlines_depth_tx;
@@ -559,8 +561,6 @@ static void OBJECT_engine_init(void *vedata)
View3D *v3d = draw_ctx->v3d;
Scene *scene = draw_ctx->scene;
RegionView3D *rv3d = draw_ctx->rv3d;
- float grid_scale = ED_view3d_grid_scale(scene, v3d, NULL);
- float grid_res;
const bool show_axis_x = (v3d->gridflag & V3D_SHOW_X) != 0;
const bool show_axis_y = (v3d->gridflag & V3D_SHOW_Y) != 0;
@@ -576,21 +576,6 @@ static void OBJECT_engine_init(void *vedata)
/* if perps */
if (winmat[3][3] == 0.0f) {
- float fov;
- float viewvecs[2][4] = {
- {1.0f, -1.0f, -1.0f, 1.0f},
- {-1.0f, 1.0f, -1.0f, 1.0f},
- };
-
- /* convert the view vectors to view space */
- for (int i = 0; i < 2; i++) {
- mul_m4_v4(wininv, viewvecs[i]);
- mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); /* perspective divide */
- }
-
- fov = angle_v3v3(viewvecs[0], viewvecs[1]) / 2.0f;
- grid_res = fabsf(tanf(fov)) / grid_scale;
-
e_data.grid_flag = (1 << 4); /* XY plane */
if (show_axis_x) {
e_data.grid_flag |= SHOW_AXIS_X;
@@ -603,14 +588,6 @@ static void OBJECT_engine_init(void *vedata)
}
}
else {
- if (rv3d->view != RV3D_VIEW_USER) {
- /* Allow 3 more subdivisions. */
- grid_scale /= powf(v3d->gridsubdiv, 3);
- }
-
- float viewdist = 1.0f / max_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
- grid_res = viewdist / grid_scale;
-
if (ELEM(rv3d->view, RV3D_VIEW_RIGHT, RV3D_VIEW_LEFT)) {
e_data.draw_grid = show_ortho_grid;
e_data.grid_flag = PLANE_YZ | SHOW_AXIS_Y | SHOW_AXIS_Z | SHOW_GRID | GRID_BACK;
@@ -688,12 +665,7 @@ static void OBJECT_engine_init(void *vedata)
dist = v3d->clip_end;
}
- e_data.grid_settings[0] = dist / 2.0f; /* gridDistance */
- e_data.grid_settings[1] = grid_res; /* gridResolution */
- e_data.grid_settings[2] = grid_scale; /* gridScale */
- e_data.grid_settings[3] = v3d->gridsubdiv; /* gridSubdiv */
- e_data.grid_settings[4] = (v3d->gridsubdiv > 1) ? 1.0f / logf(v3d->gridsubdiv) :
- 0.0f; /* 1/log(gridSubdiv) */
+ e_data.grid_distance = dist / 2.0f; /* gridDistance */
if (winmat[3][3] == 0.0f) {
e_data.grid_mesh_size = dist;
@@ -702,6 +674,8 @@ static void OBJECT_engine_init(void *vedata)
float viewdist = 1.0f / min_ff(fabsf(winmat[0][0]), fabsf(winmat[1][1]));
e_data.grid_mesh_size = viewdist * dist;
}
+
+ ED_view3d_grid_steps(scene, v3d, rv3d, e_data.grid_steps);
}
copy_v2_v2(e_data.inv_viewport_size, DRW_viewport_size_get());
@@ -1512,10 +1486,10 @@ static void OBJECT_cache_init(void *vedata)
DRWShadingGroup *grp = DRW_shgroup_create(sh_data->grid, psl->grid);
DRW_shgroup_uniform_int(grp, "gridFlag", &e_data.zneg_flag, 1);
DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.zplane_axes, 1);
- DRW_shgroup_uniform_vec4(grp, "gridSettings", e_data.grid_settings, 1);
+ DRW_shgroup_uniform_vec3(grp, "screenVecs[0]", DRW_viewport_screenvecs_get(), 2);
+ DRW_shgroup_uniform_float(grp, "gridDistance", &e_data.grid_distance, 1);
DRW_shgroup_uniform_float_copy(grp, "lineKernel", grid_line_size);
DRW_shgroup_uniform_float_copy(grp, "meshSize", e_data.grid_mesh_size);
- DRW_shgroup_uniform_float(grp, "gridOneOverLogSubdiv", &e_data.grid_settings[4], 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_call(grp, geom, NULL);
@@ -1525,6 +1499,7 @@ static void OBJECT_cache_init(void *vedata)
DRW_shgroup_uniform_vec3(grp, "planeAxes", e_data.grid_axes, 1);
DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
+ DRW_shgroup_uniform_float(grp, "gridSteps", e_data.grid_steps, ARRAY_SIZE(e_data.grid_steps));
DRW_shgroup_call(grp, geom, NULL);
grp = DRW_shgroup_create(sh_data->grid, psl->grid);
@@ -1761,6 +1736,16 @@ static void OBJECT_cache_init(void *vedata)
sgl->constraint_lines = buffer_dynlines_dashed_uniform_color(
sgl->non_meshes, gb->colorGridAxisZ, draw_ctx->sh_cfg);
+ {
+ DRWShadingGroup *grp_axes;
+ sgl->origin_xform = buffer_instance_color_axes(
+ sgl->non_meshes, DRW_cache_bone_arrows_get(), &grp_axes, draw_ctx->sh_cfg);
+
+ DRW_shgroup_state_disable(grp_axes, DRW_STATE_DEPTH_LESS_EQUAL);
+ DRW_shgroup_state_enable(grp_axes, DRW_STATE_DEPTH_ALWAYS);
+ DRW_shgroup_state_enable(grp_axes, DRW_STATE_WIRE_SMOOTH);
+ }
+
/* Force Field Curve Guide End (here because of stipple) */
/* TODO port to shader stipple */
geom = DRW_cache_screenspace_circle_get();
@@ -3701,6 +3686,15 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
DRW_shgroup_bounds(sgl, ob, theme_id);
}
+ /* Helpers for when we're transforming origins. */
+ if (scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) {
+ if (ob->base_flag & BASE_SELECTED) {
+ const float color[4] = {0.75, 0.75, 0.75, 0.5};
+ float axes_size = 1.0f;
+ DRW_buffer_add_entry(sgl->origin_xform, color, &axes_size, ob->obmat);
+ }
+ }
+
/* don't show object extras in set's */
if ((ob->base_flag & (BASE_FROM_SET | BASE_FROM_DUPLI)) == 0) {
if ((draw_ctx->object_mode & (OB_MODE_ALL_PAINT | OB_MODE_ALL_PAINT_GPENCIL)) == 0) {
@@ -3711,7 +3705,7 @@ static void OBJECT_cache_populate(void *vedata, Object *ob)
DRW_shgroup_relationship_lines(sgl, draw_ctx->depsgraph, scene, ob);
}
- const bool draw_extra = (ob->dtx != 0);
+ const bool draw_extra = ob->dtx & (OB_DRAWNAME | OB_TEXSPACE | OB_DRAWBOUNDOX);
if (draw_extra && (theme_id == TH_UNDEFINED)) {
theme_id = DRW_object_wire_theme_get(ob, view_layer, NULL);
}
diff --git a/source/blender/draw/modes/shaders/common_globals_lib.glsl b/source/blender/draw/modes/shaders/common_globals_lib.glsl
index f75ef06b6d9..e559224eb9e 100644
--- a/source/blender/draw/modes/shaders/common_globals_lib.glsl
+++ b/source/blender/draw/modes/shaders/common_globals_lib.glsl
@@ -75,11 +75,6 @@ layout(std140) uniform globalsBlock
float sizeEdgeFix;
float sizeFaceDot;
- float gridDistance;
- float gridResolution;
- float gridSubdivisions;
- float gridScale;
-
float pad_globalsBlock;
};
diff --git a/source/blender/draw/modes/shaders/object_color_axes_vert.glsl b/source/blender/draw/modes/shaders/object_color_axes_vert.glsl
new file mode 100644
index 00000000000..239dec30c42
--- /dev/null
+++ b/source/blender/draw/modes/shaders/object_color_axes_vert.glsl
@@ -0,0 +1,35 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screenVecs[3];
+
+/* ---- Instantiated Attrs ---- */
+in float axis; /* position on the axis. [0.0-1.0] is X axis, [1.0-2.0] is Y, etc... */
+in vec2 screenPos;
+in vec3 colorAxis;
+
+/* ---- Per instance Attrs ---- */
+in mat4 InstanceModelMatrix;
+in vec4 color;
+
+flat out vec4 finalColor;
+
+void main()
+{
+ float draw_size = 4.0;
+ vec3 chosen_axis = InstanceModelMatrix[int(axis)].xyz;
+ vec3 loc = InstanceModelMatrix[3].xyz;
+ vec3 wpos = loc + chosen_axis * fract(axis) * draw_size;
+ vec3 spos = screenVecs[0].xyz * screenPos.x + screenVecs[1].xyz * screenPos.y;
+ /* Scale uniformly by axis length */
+ spos *= length(chosen_axis) * draw_size;
+
+ vec4 pos_4d = vec4(wpos + spos, 1.0);
+ gl_Position = ViewProjectionMatrix * pos_4d;
+
+ finalColor.rgb = mix(colorAxis, color.rgb, color.a);
+ finalColor.a = 1.0;
+
+#ifdef USE_WORLD_CLIP_PLANES
+ world_clip_planes_calc_clip_distance(pos_4d.xyz);
+#endif
+}
diff --git a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
index 7dfbf469adc..e33aa6cdcc1 100644
--- a/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
+++ b/source/blender/draw/modes/shaders/object_empty_image_frag.glsl
@@ -37,9 +37,15 @@ void main()
if (depthMode == DEPTH_BACK) {
gl_FragDepth = 0.999999;
+#ifdef USE_WIRE
+ gl_FragDepth -= 1e-5;
+#endif
}
else if (depthMode == DEPTH_FRONT) {
gl_FragDepth = 0.000001;
+#ifdef USE_WIRE
+ gl_FragDepth -= 1e-5;
+#endif
}
else if (depthMode == DEPTH_UNCHANGED) {
gl_FragDepth = gl_FragCoord.z;
diff --git a/source/blender/draw/modes/shaders/object_grid_frag.glsl b/source/blender/draw/modes/shaders/object_grid_frag.glsl
index a20f12efd93..751d839eb79 100644
--- a/source/blender/draw/modes/shaders/object_grid_frag.glsl
+++ b/source/blender/draw/modes/shaders/object_grid_frag.glsl
@@ -9,21 +9,19 @@ in vec3 local_pos;
out vec4 FragColor;
uniform vec3 planeAxes;
-uniform vec4 gridSettings;
+uniform vec3 screenVecs[2];
+uniform float gridDistance;
uniform float meshSize;
uniform float lineKernel = 0.0;
-uniform float gridOneOverLogSubdiv;
uniform sampler2D depthBuffer;
-#define gridDistance gridSettings.x
-#define gridResolution gridSettings.y
-#define gridScale gridSettings.z
-#define gridSubdiv gridSettings.w
-
#define cameraPos (ViewMatrixInverse[3].xyz)
uniform int gridFlag;
+#define STEPS_LEN 8
+uniform float gridSteps[STEPS_LEN] = float[](0.001, 0.01, 0.1, 1.0, 10.0, 100.0, 1000.0, 10000.0);
+
#define AXIS_X (1 << 0)
#define AXIS_Y (1 << 1)
#define AXIS_Z (1 << 2)
@@ -73,10 +71,14 @@ vec3 get_axes(vec3 co, vec3 fwidthCos, float line_size)
axes_domain - (line_size + lineKernel));
}
+#define linearstep(p0, p1, v) (clamp(((v) - (p0)) / abs((p1) - (p0)), 0.0, 1.0))
+
void main()
{
vec3 wPos = local_pos * meshSize;
- vec3 fwidthPos = fwidth(wPos);
+ vec3 dFdxPos = dFdx(wPos);
+ vec3 dFdyPos = dFdy(wPos);
+ vec3 fwidthPos = abs(dFdxPos) + abs(dFdyPos);
wPos += cameraPos * planeAxes;
float dist, fade;
@@ -116,15 +118,54 @@ void main()
}
if ((gridFlag & GRID) != 0) {
- float grid_res = log(dist * gridResolution) * gridOneOverLogSubdiv;
+ /* Using `max(dot(dFdxPos, screenVecs[0]), dot(dFdyPos, screenVecs[1]))`
+ * would be more accurate, but not really necessary. */
+ float grid_res = dot(dFdxPos, screenVecs[0]);
- float blend = fract(-max(grid_res, 0.0));
- float lvl = floor(grid_res);
+ /* The gride begins to appear when it comprises 4 pixels */
+ grid_res *= 4;
/* from biggest to smallest */
- float scaleA = gridScale * pow(gridSubdiv, max(lvl - 1.0, 0.0));
- float scaleB = gridScale * pow(gridSubdiv, max(lvl + 0.0, 0.0));
- float scaleC = gridScale * pow(gridSubdiv, max(lvl + 1.0, 1.0));
+ vec4 scale;
+#if 0
+ int step_id = 0;
+ scale[0] = 0.0;
+ scale[1] = gridSteps[0];
+ while (scale[1] < grid_res && step_id != STEPS_LEN - 1) {
+ scale[0] = scale[1];
+ scale[1] = gridSteps[++step_id];
+ }
+ scale[2] = gridSteps[min(step_id + 1, STEPS_LEN - 1)];
+ scale[3] = gridSteps[min(step_id + 2, STEPS_LEN - 1)];
+#else
+ /* For more efficiency, unroll the loop above. */
+ if (gridSteps[0] > grid_res) {
+ scale = vec4(0.0, gridSteps[0], gridSteps[1], gridSteps[2]);
+ }
+ else if (gridSteps[1] > grid_res) {
+ scale = vec4(gridSteps[0], gridSteps[1], gridSteps[2], gridSteps[3]);
+ }
+ else if (gridSteps[2] > grid_res) {
+ scale = vec4(gridSteps[1], gridSteps[2], gridSteps[3], gridSteps[4]);
+ }
+ else if (gridSteps[3] > grid_res) {
+ scale = vec4(gridSteps[2], gridSteps[3], gridSteps[4], gridSteps[5]);
+ }
+ else if (gridSteps[4] > grid_res) {
+ scale = vec4(gridSteps[3], gridSteps[4], gridSteps[5], gridSteps[6]);
+ }
+ else if (gridSteps[5] > grid_res) {
+ scale = vec4(gridSteps[4], gridSteps[5], gridSteps[6], gridSteps[7]);
+ }
+ else if (gridSteps[6] > grid_res) {
+ scale = vec4(gridSteps[5], gridSteps[6], gridSteps[7], gridSteps[7]);
+ }
+ else {
+ scale = vec4(gridSteps[6], gridSteps[7], gridSteps[7], gridSteps[7]);
+ }
+#endif
+ float blend = 1.0 - linearstep(scale[0], scale[1], grid_res);
+ blend = blend * blend * blend;
vec2 grid_pos, grid_fwidth;
if ((gridFlag & PLANE_XZ) != 0) {
@@ -140,9 +181,9 @@ void main()
grid_fwidth = fwidthPos.xy;
}
- float gridA = get_grid(grid_pos, grid_fwidth, scaleA);
- float gridB = get_grid(grid_pos, grid_fwidth, scaleB);
- float gridC = get_grid(grid_pos, grid_fwidth, scaleC);
+ float gridA = get_grid(grid_pos, grid_fwidth, scale[1]);
+ float gridB = get_grid(grid_pos, grid_fwidth, scale[2]);
+ float gridC = get_grid(grid_pos, grid_fwidth, scale[3]);
FragColor = colorGrid;
FragColor.a *= gridA * blend;
diff --git a/source/blender/draw/modes/shaders/object_grid_vert.glsl b/source/blender/draw/modes/shaders/object_grid_vert.glsl
index d247967b03a..496bb011c74 100644
--- a/source/blender/draw/modes/shaders/object_grid_vert.glsl
+++ b/source/blender/draw/modes/shaders/object_grid_vert.glsl
@@ -3,14 +3,8 @@
* Clément Foucault */
uniform vec3 planeAxes;
-uniform vec4 gridSettings;
uniform float meshSize;
-#define gridDistance gridSettings.x
-#define gridResolution gridSettings.y
-#define gridScale gridSettings.z
-#define gridSubdiv gridSettings.w
-
uniform int gridFlag;
#define cameraPos (ViewMatrixInverse[3].xyz)
diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c
index 1649744ba8d..d80b96f0d74 100644
--- a/source/blender/editors/animation/anim_channels_defines.c
+++ b/source/blender/editors/animation/anim_channels_defines.c
@@ -4847,7 +4847,7 @@ void ANIM_channel_draw_widgets(const bContext *C,
/* step 4) draw text - check if renaming widget is in use... */
if (is_being_renamed) {
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
/* draw renaming widget if we can get RNA pointer for it
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index 7e913014a87..61b8e4a2341 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -3114,6 +3114,7 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, gpl, ANIMTYPE_GPLAYER);
/* update other layer status */
BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_autolock_set(gpd);
}
/* Grease Pencil updates */
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index a78a63f1347..48493c9e961 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -630,9 +630,8 @@ static bAnimListElem *make_new_animlistelem(void *data,
/* do specifics */
switch (datatype) {
case ANIMTYPE_SUMMARY: {
- /* nothing to include for now... this is just a dummy wrappy around all the other channels
- * in the DopeSheet, and gets included at the start of the list
- */
+ /* Nothing to include for now... this is just a dummy wrapper around
+ * all the other channels in the DopeSheet, and gets included at the start of the list. */
ale->key_data = NULL;
ale->datatype = ALE_ALL;
break;
diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c
index fad9a1a8e49..5b729c856c0 100644
--- a/source/blender/editors/animation/anim_ipo_utils.c
+++ b/source/blender/editors/animation/anim_ipo_utils.c
@@ -122,7 +122,7 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu)
MEM_freeN(constName);
}
}
- else if (ptr.data != ptr.id.data) {
+ else if (ptr.data != ptr.owner_id) {
PropertyRNA *nameprop = RNA_struct_name_property(ptr.type);
if (nameprop) {
/* this gets a string which will need to be freed */
diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c
index ded59466370..8c873eb6b45 100644
--- a/source/blender/editors/animation/anim_markers.c
+++ b/source/blender/editors/animation/anim_markers.c
@@ -486,7 +486,7 @@ static void draw_marker(
float name_y = UI_DPI_FAC * 18;
/* Give an offset to the marker name when selected,
* or when near the current frame (5 frames range, starting from the current one). */
- if ((marker->flag & SELECT) || (IN_RANGE_INCL(marker->frame, cfra, cfra - 4))) {
+ if ((marker->flag & SELECT) || (IN_RANGE_INCL(marker->frame, cfra - 4, cfra))) {
name_y += UI_DPI_FAC * 10;
}
draw_marker_name(fstyle, marker, xpos, name_y);
diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c
index 7a5b57b1ce6..bd4886817cd 100644
--- a/source/blender/editors/animation/anim_motion_paths.c
+++ b/source/blender/editors/animation/anim_motion_paths.c
@@ -60,9 +60,8 @@ typedef struct MPathTarget {
Object *ob; /* source object */
bPoseChannel *pchan; /* source posechannel (if applicable) */
- /* "Evaluated" Copies (these come from the background COW copie
- * that provide all the coordinates we want to save off)
- */
+ /* "Evaluated" Copies (these come from the background COW copy
+ * that provide all the coordinates we want to save off). */
Object *ob_eval; /* evaluated object */
} MPathTarget;
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 935d11a388f..7b9e6a10f44 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -218,7 +218,7 @@ static int add_driver_with_target(ReportList *UNUSED(reports),
/* Create a driver variable for the target
* - For transform properties, we want to automatically use "transform channel" instead
- * (The only issue is with quat rotations vs euler channels...)
+ * (The only issue is with quaternion rotations vs euler channels...)
* - To avoid problems with transform properties depending on the final transform that they
* control (thus creating pseudo-cycles - see T48734), we don't use transform channels
* when both the source and destinations are in same places.
@@ -934,7 +934,7 @@ static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C,
EnumPropertyItem *input = prop_driver_create_mapping_types;
EnumPropertyItem *item = NULL;
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
int index;
@@ -946,7 +946,7 @@ static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C,
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
const bool is_array = RNA_property_array_check(prop);
while (input->identifier) {
@@ -971,7 +971,7 @@ static const EnumPropertyItem *driver_mapping_type_itemsf(bContext *C,
static bool add_driver_button_poll(bContext *C)
{
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
int index;
bool driven, special;
@@ -979,7 +979,7 @@ static bool add_driver_button_poll(bContext *C)
/* this operator can only run if there's a property button active, and it can be animated */
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (!(ptr.id.data && ptr.data && prop)) {
+ if (!(ptr.owner_id && ptr.data && prop)) {
return false;
}
if (!RNA_property_animateable(&ptr, prop)) {
@@ -995,7 +995,7 @@ static bool add_driver_button_poll(bContext *C)
* (i.e. "manual/add later"). */
static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_type)
{
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
int index;
int success = 0;
@@ -1006,12 +1006,13 @@ static int add_driver_button_none(bContext *C, wmOperator *op, short mapping_typ
index = -1;
}
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
if (path) {
- success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
+ success += ANIM_add_driver(
+ op->reports, ptr.owner_id, path, index, flags, DRIVER_TYPE_PYTHON);
MEM_freeN(path);
}
}
@@ -1095,28 +1096,29 @@ static void UNUSED_FUNCTION(ANIM_OT_driver_button_add_menu)(wmOperatorType *ot)
static int add_driver_button_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
int index;
/* try to find driver using property retrieved from UI */
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
/* 1) Create a new "empty" driver for this property */
char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
short success = 0;
if (path) {
- success += ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
+ success += ANIM_add_driver(
+ op->reports, ptr.owner_id, path, index, flags, DRIVER_TYPE_PYTHON);
MEM_freeN(path);
}
if (success) {
/* send updates */
UI_context_update_anim_flag(C);
- DEG_id_tag_update(ptr.id.data, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(ptr.owner_id, ID_RECALC_COPY_ON_WRITE);
DEG_relations_tag_update(CTX_data_main(C));
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL);
}
@@ -1149,7 +1151,7 @@ void ANIM_OT_driver_button_add(wmOperatorType *ot)
static int remove_driver_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
short success = 0;
int index;
@@ -1162,11 +1164,11 @@ static int remove_driver_button_exec(bContext *C, wmOperator *op)
index = -1;
}
- if (ptr.id.data && ptr.data && prop) {
+ if (ptr.owner_id && ptr.data && prop) {
char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
if (path) {
- success = ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0);
+ success = ANIM_remove_driver(op->reports, ptr.owner_id, path, index, 0);
MEM_freeN(path);
}
@@ -1205,14 +1207,14 @@ void ANIM_OT_driver_button_remove(wmOperatorType *ot)
static int edit_driver_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
int index;
/* try to find driver using property retrieved from UI */
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop) {
+ if (ptr.owner_id && ptr.data && prop) {
UI_popover_panel_invoke(C, "GRAPH_PT_drivers_popover", true, op->reports);
}
@@ -1239,7 +1241,7 @@ void ANIM_OT_driver_button_edit(wmOperatorType *ot)
static int copy_driver_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
short success = 0;
int index;
@@ -1247,12 +1249,12 @@ static int copy_driver_button_exec(bContext *C, wmOperator *op)
/* try to create driver using property retrieved from UI */
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
if (path) {
/* only copy the driver for the button that this was involved for */
- success = ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0);
+ success = ANIM_copy_driver(op->reports, ptr.owner_id, path, index, 0);
UI_context_update_anim_flag(C);
@@ -1283,7 +1285,7 @@ void ANIM_OT_copy_driver_button(wmOperatorType *ot)
static int paste_driver_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
short success = 0;
int index;
@@ -1291,18 +1293,18 @@ static int paste_driver_button_exec(bContext *C, wmOperator *op)
/* try to create driver using property retrieved from UI */
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
char *path = BKE_animdata_driver_path_hack(C, &ptr, prop, NULL);
if (path) {
/* only copy the driver for the button that this was involved for */
- success = ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
+ success = ANIM_paste_driver(op->reports, ptr.owner_id, path, index, 0);
UI_context_update_anim_flag(C);
DEG_relations_tag_update(CTX_data_main(C));
- DEG_id_tag_update(ptr.id.data, ID_RECALC_ANIMATION);
+ DEG_id_tag_update(ptr.owner_id, ID_RECALC_ANIMATION);
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME_PROP, NULL); // XXX
diff --git a/source/blender/editors/animation/fmodifier_ui.c b/source/blender/editors/animation/fmodifier_ui.c
index b42e8102c5b..705351522f8 100644
--- a/source/blender/editors/animation/fmodifier_ui.c
+++ b/source/blender/editors/animation/fmodifier_ui.c
@@ -197,7 +197,7 @@ static void draw_modifier__generator(uiLayout *layout,
&data->poly_order,
1,
100,
- 0,
+ 1,
0,
TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)"));
UI_but_func_set(but, validate_fmodifier_cb, fcm, fcurve_owner_id);
@@ -335,7 +335,7 @@ static void draw_modifier__generator(uiLayout *layout,
&data->poly_order,
1,
100,
- 0,
+ 1,
0,
TIP_("'Order' of the Polynomial (for a polynomial with n terms, 'order' is n-1)"));
UI_but_func_set(but, validate_fmodifier_cb, fcm, fcurve_owner_id);
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index 889d27480df..ca7e0eae136 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -814,8 +814,10 @@ static void draw_keylist(View2D *v2d,
uint outline_color_id = GPU_vertformat_attr_add(
format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+
GPU_program_point_size(true);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ immUniform1f("outline_scale", 1.0f);
immUniform2f(
"ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
immBegin(GPU_PRIM_POINTS, key_len);
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index dcc596e67e1..0f8b8742659 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -222,7 +222,7 @@ FCurve *verify_fcurve(Main *bmain,
/* sync bone group colors if applicable */
if (ptr && (ptr->type == &RNA_PoseBone)) {
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
bPose *pose = ob->pose;
bActionGroup *grp;
@@ -286,7 +286,7 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin
PropertyRNA *prop;
int old_flag = fcu->flag;
- if ((ptr->id.data == NULL) && (ptr->data == NULL)) {
+ if ((ptr->owner_id == NULL) && (ptr->data == NULL)) {
BKE_report(reports, RPT_ERROR, "No RNA pointer available to retrieve values for this fcurve");
return;
}
@@ -294,7 +294,7 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin
/* try to get property we should be affecting */
if (RNA_path_resolve_property(ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
/* property not found... */
- const char *idname = (ptr->id.data) ? ((ID *)ptr->id.data)->name : TIP_("<No ID pointer>");
+ const char *idname = (ptr->owner_id) ? ptr->owner_id->name : TIP_("<No ID pointer>");
BKE_reportf(reports,
RPT_ERROR,
@@ -1203,7 +1203,7 @@ bool insert_keyframe_direct(ReportList *reports,
}
/* if no property given yet, try to validate from F-Curve info */
- if ((ptr.id.data == NULL) && (ptr.data == NULL)) {
+ if ((ptr.owner_id == NULL) && (ptr.data == NULL)) {
BKE_report(
reports, RPT_ERROR, "No RNA pointer available to retrieve values for keyframing from");
return false;
@@ -1214,7 +1214,7 @@ bool insert_keyframe_direct(ReportList *reports,
/* try to get property we should be affecting */
if (RNA_path_resolve_property(&ptr, fcu->rna_path, &tmp_ptr, &prop) == false) {
/* property not found... */
- const char *idname = (ptr.id.data) ? ((ID *)ptr.id.data)->name : TIP_("<No ID pointer>");
+ const char *idname = (ptr.owner_id) ? ptr.owner_id->name : TIP_("<No ID pointer>");
BKE_reportf(reports,
RPT_ERROR,
@@ -1544,9 +1544,9 @@ static bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra)
static void deg_tag_after_keyframe_delete(Main *bmain, ID *id, AnimData *adt)
{
if (adt->action == NULL) {
- /* In the case last f-curve wes removed need to inform dependency graph
+ /* In the case last f-curve was removed need to inform dependency graph
* about relations update, since it needs to get rid of animation operation
- * for this datablock. */
+ * for this data-block. */
DEG_id_tag_update_ex(bmain, id, ID_RECALC_ANIMATION_NO_FLUSH);
DEG_relations_tag_update(bmain);
}
@@ -2350,7 +2350,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
ToolSettings *ts = scene->toolsettings;
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
char *path;
uiBut *but;
@@ -2369,7 +2369,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
- if ((ptr.id.data && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) {
+ if ((ptr.owner_id && ptr.data && prop) && RNA_property_animateable(&ptr, prop)) {
if (ptr.type == &RNA_NlaStrip) {
/* Handle special properties for NLA Strips, whose F-Curves are stored on the
* strips themselves. These are stored separately or else the properties will
@@ -2435,7 +2435,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
success = insert_keyframe(bmain,
op->reports,
- ptr.id.data,
+ ptr.owner_id,
NULL,
group,
path,
@@ -2473,7 +2473,7 @@ static int insert_key_button_exec(bContext *C, wmOperator *op)
}
if (success) {
- ID *id = ptr.id.data;
+ ID *id = ptr.owner_id;
AnimData *adt = BKE_animdata_from_id(id);
if (adt->action != NULL) {
DEG_id_tag_update(&adt->action->id, ID_RECALC_ANIMATION_NO_FLUSH);
@@ -2513,7 +2513,7 @@ void ANIM_OT_keyframe_insert_button(wmOperatorType *ot)
static int delete_key_button_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
Main *bmain = CTX_data_main(C);
char *path;
@@ -2528,13 +2528,13 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
- if (ptr.id.data && ptr.data && prop) {
+ if (ptr.owner_id && ptr.data && prop) {
if (BKE_nlastrip_has_curves_for_property(&ptr, prop)) {
/* Handle special properties for NLA Strips, whose F-Curves are stored on the
* strips themselves. These are stored separately or else the properties will
* not have any effect.
*/
- ID *id = ptr.id.data;
+ ID *id = ptr.owner_id;
NlaStrip *strip = (NlaStrip *)ptr.data;
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), 0);
@@ -2577,7 +2577,7 @@ static int delete_key_button_exec(bContext *C, wmOperator *op)
}
success = delete_keyframe(
- bmain, op->reports, ptr.id.data, NULL, NULL, path, index, cfra, 0);
+ bmain, op->reports, ptr.owner_id, NULL, NULL, path, index, cfra, 0);
MEM_freeN(path);
}
else if (G.debug & G_DEBUG) {
@@ -2622,7 +2622,7 @@ void ANIM_OT_keyframe_delete_button(wmOperatorType *ot)
static int clear_key_button_exec(bContext *C, wmOperator *op)
{
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
Main *bmain = CTX_data_main(C);
char *path;
@@ -2636,7 +2636,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
- if (ptr.id.data && ptr.data && prop) {
+ if (ptr.owner_id && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
@@ -2645,7 +2645,7 @@ static int clear_key_button_exec(bContext *C, wmOperator *op)
index = -1;
}
- success += clear_keyframe(bmain, op->reports, ptr.id.data, NULL, NULL, path, index, 0);
+ success += clear_keyframe(bmain, op->reports, ptr.owner_id, NULL, NULL, path, index, 0);
MEM_freeN(path);
}
else if (G.debug & G_DEBUG) {
diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c
index ccd0fc54611..258c0e4f1f6 100644
--- a/source/blender/editors/animation/keyingsets.c
+++ b/source/blender/editors/animation/keyingsets.c
@@ -287,7 +287,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
KeyingSet *ks = NULL;
PropertyRNA *prop = NULL;
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
char *path = NULL;
short success = 0;
int index = 0, pflag = 0;
@@ -332,7 +332,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
}
/* check if property is able to be added */
- if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
+ if (ptr.owner_id && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
@@ -348,7 +348,7 @@ static int add_keyingset_button_exec(bContext *C, wmOperator *op)
}
/* add path to this setting */
- BKE_keyingset_add_path(ks, ptr.id.data, NULL, path, index, pflag, KSP_GROUP_KSNAME);
+ BKE_keyingset_add_path(ks, ptr.owner_id, NULL, path, index, pflag, KSP_GROUP_KSNAME);
ks->active_path = BLI_listbase_count(&ks->paths);
success = 1;
@@ -393,7 +393,7 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
KeyingSet *ks = NULL;
PropertyRNA *prop = NULL;
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
char *path = NULL;
short success = 0;
int index = 0;
@@ -420,14 +420,14 @@ static int remove_keyingset_button_exec(bContext *C, wmOperator *op)
ks = BLI_findlink(&scene->keyingsets, scene->active_keyingset - 1);
}
- if (ptr.id.data && ptr.data && prop) {
+ if (ptr.owner_id && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
KS_Path *ksp;
/* try to find a path matching this description */
- ksp = BKE_keyingset_find_path(ks, ptr.id.data, ks->name, path, index, KSP_GROUP_KSNAME);
+ ksp = BKE_keyingset_find_path(ks, ptr.owner_id, ks->name, path, index, KSP_GROUP_KSNAME);
if (ksp) {
BKE_keyingset_free_path(ks, ksp);
@@ -712,9 +712,9 @@ int ANIM_scene_get_keyingset_index(Scene *scene, KeyingSet *ks)
}
}
- /* still here, so try builtins list too
- * - builtins are from (<= -1)
- * - none/invalid is (= 0)
+ /* Still here, so try built-ins list too:
+ * - Built-ins are from (<= -1).
+ * - None/Invalid is (= 0).
*/
index = BLI_findindex(&builtin_keyingsets, ks);
if (index != -1) {
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index d2fa77f90be..1073034383d 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -769,7 +769,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op)
EditBone *ebone = ebone_iter->temp.ebone;
- /* copy flags incase bone is pre-existing data */
+ /* Copy flags in case bone is pre-existing data. */
ebone->flag = (ebone->flag & ~flag_copy) | (ebone_iter->flag & flag_copy);
if (ebone_iter->parent == NULL) {
diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c
index 4e6661b1d15..c4c10549da3 100644
--- a/source/blender/editors/armature/armature_edit.c
+++ b/source/blender/editors/armature/armature_edit.c
@@ -62,22 +62,10 @@
/* ************************** Object Tools Exports ******************************* */
/* NOTE: these functions are exported to the Object module to be called from the tools there */
-void ED_armature_transform_apply(Main *bmain, Object *ob, float mat[4][4], const bool do_props)
-{
- bArmature *arm = ob->data;
-
- /* Put the armature into editmode */
- ED_armature_to_edit(arm);
-
- /* Transform the bones */
- ED_armature_transform_bones(arm, mat, do_props);
-
- /* Turn the list into an armature */
- ED_armature_from_edit(bmain, arm);
- ED_armature_edit_free(arm);
-}
-
-void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props)
+/**
+ * See #BKE_armature_transform for object-mode transform.
+ */
+void ED_armature_edit_transform(bArmature *arm, const float mat[4][4], const bool do_props)
{
EditBone *ebone;
float scale = mat4_to_scale(mat); /* store the scale of the matrix here to use on envelopes */
@@ -114,21 +102,13 @@ void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const b
}
}
-void ED_armature_transform(Main *bmain, bArmature *arm, float mat[4][4], const bool do_props)
+void ED_armature_transform(bArmature *arm, const float mat[4][4], const bool do_props)
{
if (arm->edbo) {
- ED_armature_transform_bones(arm, mat, do_props);
+ ED_armature_edit_transform(arm, mat, do_props);
}
else {
- /* Put the armature into editmode */
- ED_armature_to_edit(arm);
-
- /* Transform the bones */
- ED_armature_transform_bones(arm, mat, do_props);
-
- /* Go back to object mode*/
- ED_armature_from_edit(bmain, arm);
- ED_armature_edit_free(arm);
+ BKE_armature_transform(arm, mat, do_props);
}
}
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index 569eb7e2e04..fa562ab0f44 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -30,7 +30,6 @@ struct wmOperatorType;
struct Base;
struct Object;
struct Scene;
-struct bAction;
struct bContext;
struct bPoseChannel;
diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c
index 23ddf77e63d..eff621d7b71 100644
--- a/source/blender/editors/armature/armature_select.c
+++ b/source/blender/editors/armature/armature_select.c
@@ -46,6 +46,7 @@
#include "ED_armature.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_view3d.h"
@@ -356,6 +357,8 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEv
}
}
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+
ED_armature_edit_sync_selection(arm->edbo);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
@@ -1027,6 +1030,8 @@ static int armature_de_select_all_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
return OPERATOR_FINISHED;
@@ -1148,6 +1153,8 @@ static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op))
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
}
MEM_freeN(objects);
+
+ ED_outliner_select_sync_from_edit_bone_tag(C);
return OPERATOR_FINISHED;
}
@@ -1178,6 +1185,8 @@ static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op))
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
}
MEM_freeN(objects);
+
+ ED_outliner_select_sync_from_edit_bone_tag(C);
return OPERATOR_FINISHED;
}
@@ -1569,6 +1578,8 @@ static int armature_select_similar_exec(bContext *C, wmOperator *op)
#undef STRUCT_SIZE_AND_OFFSET
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+
return OPERATOR_FINISHED;
}
@@ -1663,6 +1674,8 @@ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+
ED_armature_edit_sync_selection(arm->edbo);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
@@ -1748,6 +1761,8 @@ static int armature_select_mirror_exec(bContext *C, wmOperator *op)
arm->act_edbone = ebone_mirror_act;
}
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+
ED_armature_edit_sync_selection(arm->edbo);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
@@ -1876,6 +1891,7 @@ static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const
if (changed) {
arm->act_edbone = ebone_dst;
+ ED_outliner_select_sync_from_edit_bone_tag(C);
ED_armature_edit_sync_selection(arm->edbo);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c
index d8777b7e0b7..cd299906b4c 100644
--- a/source/blender/editors/armature/armature_utils.c
+++ b/source/blender/editors/armature/armature_utils.c
@@ -381,23 +381,37 @@ void armature_tag_unselect(bArmature *arm)
void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bool check_select)
{
+ /* TODO When this function is called by property updates,
+ * cancelling the value change will not restore mirrored bone correctly. */
+
+ /* Currently check_select==true when this function is called from a transform operator,
+ * eg. from 3d viewport. */
+
/* no layer check, correct mirror is more important */
if (!check_select || ebo->flag & (BONE_TIPSEL | BONE_ROOTSEL)) {
EditBone *eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo);
if (eboflip) {
- /* we assume X-axis flipping for now */
- if (check_select && ebo->flag & BONE_TIPSEL) {
- EditBone *children;
+ /* We assume X-axis flipping for now. */
+
+ /* Always mirror roll, since it can be changed by moving either head or tail. */
+ eboflip->roll = -ebo->roll;
+
+ if (!check_select || ebo->flag & BONE_TIPSEL) {
+ /* Mirror tail properties. */
eboflip->tail[0] = -ebo->tail[0];
eboflip->tail[1] = ebo->tail[1];
eboflip->tail[2] = ebo->tail[2];
eboflip->rad_tail = ebo->rad_tail;
- eboflip->roll = -ebo->roll;
eboflip->curve_out_x = -ebo->curve_out_x;
+ eboflip->curve_out_y = ebo->curve_out_y;
+ eboflip->scale_out_x = ebo->scale_out_x;
+ eboflip->scale_out_y = ebo->scale_out_y;
+ eboflip->ease2 = ebo->ease2;
eboflip->roll2 = -ebo->roll2;
- /* Also move connected children, in case children's name aren't mirrored properly */
+ /* Also move connected children, in case children's name aren't mirrored properly. */
+ EditBone *children;
for (children = arm->edbo->first; children; children = children->next) {
if (children->parent == eboflip && children->flag & BONE_CONNECTED) {
copy_v3_v3(children->head, eboflip->tail);
@@ -405,32 +419,39 @@ void ED_armature_ebone_transform_mirror_update(bArmature *arm, EditBone *ebo, bo
}
}
}
+
if (!check_select || ebo->flag & BONE_ROOTSEL) {
+ /* Mirror head properties. */
eboflip->head[0] = -ebo->head[0];
eboflip->head[1] = ebo->head[1];
eboflip->head[2] = ebo->head[2];
eboflip->rad_head = ebo->rad_head;
- eboflip->roll = -ebo->roll;
+
eboflip->curve_in_x = -ebo->curve_in_x;
+ eboflip->curve_in_y = ebo->curve_in_y;
+ eboflip->scale_in_x = ebo->scale_in_x;
+ eboflip->scale_in_y = ebo->scale_in_y;
+ eboflip->ease1 = ebo->ease1;
eboflip->roll1 = -ebo->roll1;
- /* Also move connected parent, in case parent's name isn't mirrored properly */
+ /* Also move connected parent, in case parent's name isn't mirrored properly. */
if (eboflip->parent && eboflip->flag & BONE_CONNECTED) {
EditBone *parent = eboflip->parent;
copy_v3_v3(parent->tail, eboflip->head);
parent->rad_tail = ebo->rad_head;
}
}
+
if (!check_select || ebo->flag & BONE_SELECTED) {
+ /* Mirror bone body properties (both head and tail are selected). */
+ /* TODO: These values can also be changed from pose mode,
+ * so only mirroring them in edit mode is not ideal. */
eboflip->dist = ebo->dist;
- eboflip->roll = -ebo->roll;
+ eboflip->weight = ebo->weight;
+
+ eboflip->segments = ebo->segments;
eboflip->xwidth = ebo->xwidth;
eboflip->zwidth = ebo->zwidth;
-
- eboflip->curve_in_x = -ebo->curve_in_x;
- eboflip->curve_out_x = -ebo->curve_out_x;
- eboflip->roll1 = -ebo->roll1;
- eboflip->roll2 = -ebo->roll2;
}
}
}
diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c
index 8434fee6e78..a59067e60c1 100644
--- a/source/blender/editors/armature/pose_select.c
+++ b/source/blender/editors/armature/pose_select.c
@@ -54,6 +54,7 @@
#include "ED_keyframing.h"
#include "ED_mesh.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_view3d.h"
@@ -449,6 +450,8 @@ static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEve
selectconnected_posebonechildren(base->object, curBone, extend);
}
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+
ED_pose_bone_select_tag_update(base->object);
return OPERATOR_FINISHED;
@@ -514,6 +517,8 @@ static int pose_de_select_all_exec(bContext *C, wmOperator *op)
}
CTX_DATA_END;
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
return OPERATOR_FINISHED;
@@ -560,6 +565,8 @@ static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+
ED_pose_bone_select_tag_update(ob);
return OPERATOR_FINISHED;
}
@@ -624,6 +631,8 @@ static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op
return OPERATOR_CANCELLED;
}
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+
return OPERATOR_FINISHED;
}
@@ -712,6 +721,8 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+
ED_pose_bone_select_tag_update(ob);
return OPERATOR_FINISHED;
@@ -796,7 +807,7 @@ static bool pose_select_same_group(bContext *C, bool extend)
group_flags = NULL;
ob_index = -1;
ob_prev = NULL;
- CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object, *ob) {
+ CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
if (ob != ob_prev) {
ob_index++;
group_flags = group_flags_array + (ob_index * groups_len);
@@ -1061,6 +1072,8 @@ static int pose_select_grouped_exec(bContext *C, wmOperator *op)
/* report done status */
if (changed) {
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+
return OPERATOR_FINISHED;
}
else {
@@ -1172,6 +1185,8 @@ static int pose_select_mirror_exec(bContext *C, wmOperator *op)
}
MEM_freeN(objects);
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c
index c8e79b879a4..6274eb549da 100644
--- a/source/blender/editors/armature/pose_slide.c
+++ b/source/blender/editors/armature/pose_slide.c
@@ -442,7 +442,7 @@ static void pose_slide_apply_props(tPoseSlideOp *pso,
tPChanFCurveLink *pfl,
const char prop_prefix[])
{
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
LinkData *ld;
int len = strlen(pfl->pchan_path);
diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c
index c93531bb6cc..d7650db546d 100644
--- a/source/blender/editors/curve/editcurve.c
+++ b/source/blender/editors/curve/editcurve.c
@@ -51,6 +51,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -5679,6 +5680,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event)
},
mval,
NULL,
+ NULL,
location,
NULL);
@@ -7104,14 +7106,15 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op))
(void)depsgraph;
Object *object = CTX_data_active_object(C);
+ Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
Curve *curve = (Curve *)object->data;
float min[3], max[3], size[3], loc[3];
int a;
- BLI_assert(object->runtime.curve_cache != NULL);
+ BLI_assert(object_eval->runtime.curve_cache != NULL);
INIT_MINMAX(min, max);
- BKE_displist_minmax(&object->runtime.curve_cache->disp, min, max);
+ BKE_displist_minmax(&object_eval->runtime.curve_cache->disp, min, max);
mid_v3_v3v3(loc, min, max);
@@ -7138,6 +7141,7 @@ static int match_texture_space_exec(bContext *C, wmOperator *UNUSED(op))
curve->texflag &= ~CU_AUTOSPACE;
WM_event_add_notifier(C, NC_GEOM | ND_DATA, curve);
+ DEG_id_tag_update(&curve->id, ID_RECALC_GEOMETRY);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c
index 5e0053782d4..c7c19aa2d02 100644
--- a/source/blender/editors/curve/editcurve_paint.c
+++ b/source/blender/editors/curve/editcurve_paint.c
@@ -120,7 +120,7 @@ struct CurveDrawData {
struct {
float mouse[2];
- /* used incase we can't calculate the depth */
+ /* Used in case we can't calculate the depth. */
float location_world[3];
float location_world_valid[3];
@@ -1053,7 +1053,7 @@ static int curve_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input");
- /* fallback (incase we can't find the depth on first test) */
+ /* Fallback (in case we can't find the depth on first test). */
{
const float mval_fl[2] = {UNPACK2(event->mval)};
float center[3];
diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c
index d3f0ebfda3c..f67ccf1e4bd 100644
--- a/source/blender/editors/curve/editcurve_select.c
+++ b/source/blender/editors/curve/editcurve_select.c
@@ -1417,7 +1417,7 @@ void CURVE_OT_select_nth(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Checker Deselect";
- ot->description = "Deselect every other vertex";
+ ot->description = "Deselect every Nth point starting from the active one";
ot->idname = "CURVE_OT_select_nth";
/* api callbacks */
diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c
index f0c1abff201..781eb2634fb 100644
--- a/source/blender/editors/curve/editfont.c
+++ b/source/blender/editors/curve/editfont.c
@@ -71,7 +71,11 @@
static int kill_selection(Object *obedit, int ins);
-/************************* utilities ******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Utilities
+ * \{ */
static wchar_t findaccent(wchar_t char1, unsigned int code)
{
@@ -440,8 +444,48 @@ static void text_update_edited(bContext *C, Object *obedit, int mode)
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
}
+static int kill_selection(Object *obedit, int ins) /* 1 == new character */
+{
+ Curve *cu = obedit->data;
+ EditFont *ef = cu->editfont;
+ int selend, selstart, direction;
+ int offset = 0;
+ int getfrom;
+
+ direction = BKE_vfont_select_get(obedit, &selstart, &selend);
+ if (direction) {
+ int size;
+ if (ins) {
+ offset = 1;
+ }
+ if (ef->pos >= selstart) {
+ ef->pos = selstart + offset;
+ }
+ if ((direction == -1) && ins) {
+ selstart++;
+ selend++;
+ }
+ getfrom = selend + offset;
+ if (ins == 0) {
+ getfrom++;
+ }
+ size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t));
+ memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size);
+ memmove(ef->textbufinfo + selstart,
+ ef->textbufinfo + getfrom,
+ ((ef->len - selstart) + offset) * sizeof(CharInfo));
+ ef->len -= ((selend - selstart) + 1);
+ ef->selstart = ef->selend = 0;
+ }
+
+ return (direction);
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Generic Paste Functions */
+/** \name Generic Paste Functions
+ * \{ */
/* text_update_edited(C, scene, obedit, 1, FO_EDIT); */
static bool font_paste_wchar(Object *obedit,
@@ -506,8 +550,11 @@ static bool font_paste_utf8(bContext *C, const char *str, const size_t str_len)
return retval;
}
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Paste From File*/
+/** \name Paste From File Operator
+ * \{ */
static int paste_from_file(bContext *C, ReportList *reports, const char *filename)
{
@@ -585,7 +632,11 @@ void FONT_OT_text_paste_from_file(wmOperatorType *ot)
FILE_SORT_ALPHA);
}
-/******************* text to object operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Text To Object
+ * \{ */
static void txt_add_object(bContext *C, TextLine *firstline, int totline, const float offset[3])
{
@@ -703,46 +754,11 @@ void ED_text_to_object(bContext *C, Text *text, const bool split_lines)
}
}
-/********************** utilities ***************************/
-
-static int kill_selection(Object *obedit, int ins) /* 1 == new character */
-{
- Curve *cu = obedit->data;
- EditFont *ef = cu->editfont;
- int selend, selstart, direction;
- int offset = 0;
- int getfrom;
-
- direction = BKE_vfont_select_get(obedit, &selstart, &selend);
- if (direction) {
- int size;
- if (ins) {
- offset = 1;
- }
- if (ef->pos >= selstart) {
- ef->pos = selstart + offset;
- }
- if ((direction == -1) && ins) {
- selstart++;
- selend++;
- }
- getfrom = selend + offset;
- if (ins == 0) {
- getfrom++;
- }
- size = (ef->len * sizeof(wchar_t)) - (selstart * sizeof(wchar_t)) + (offset * sizeof(wchar_t));
- memmove(ef->textbuf + selstart, ef->textbuf + getfrom, size);
- memmove(ef->textbufinfo + selstart,
- ef->textbufinfo + getfrom,
- ((ef->len - selstart) + offset) * sizeof(CharInfo));
- ef->len -= ((selend - selstart) + 1);
- ef->selstart = ef->selend = 0;
- }
-
- return (direction);
-}
+/** \} */
-/******************* set style operator ********************/
+/* -------------------------------------------------------------------- */
+/** \name Set Style Operator
+ * \{ */
static const EnumPropertyItem style_items[] = {
{CU_CHINFO_BOLD, "BOLD", 0, "Bold", ""},
@@ -806,7 +822,11 @@ void FONT_OT_style_set(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "clear", 0, "Clear", "Clear style rather than setting it");
}
-/******************* toggle style operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Style Operator
+ * \{ */
static int toggle_style_exec(bContext *C, wmOperator *op)
{
@@ -845,8 +865,11 @@ void FONT_OT_style_toggle(wmOperatorType *ot)
ot->srna, "style", style_items, CU_CHINFO_BOLD, "Style", "Style to set selection to");
}
+/** \} */
+
/* -------------------------------------------------------------------- */
-/* Select All */
+/** \name Select All Operator
+ * \{ */
static int font_select_all_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -883,7 +906,11 @@ void FONT_OT_select_all(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/******************* copy text operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Copy Text Operator
+ * \{ */
static void copy_selection(Object *obedit)
{
@@ -932,7 +959,11 @@ void FONT_OT_text_copy(wmOperatorType *ot)
ot->poll = ED_operator_editfont;
}
-/******************* cut text operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Cut Text Operator
+ * \{ */
static int cut_text_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -966,7 +997,11 @@ void FONT_OT_text_cut(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/******************* paste text operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Paste Text Operator
+ * \{ */
static bool paste_selection(Object *obedit, ReportList *reports)
{
@@ -1066,7 +1101,11 @@ void FONT_OT_text_paste(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/************************ move operator ************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Move Operator
+ * \{ */
static const EnumPropertyItem move_type_items[] = {
{LINE_BEGIN, "LINE_BEGIN", 0, "Line Begin", ""},
@@ -1232,7 +1271,11 @@ void FONT_OT_move(wmOperatorType *ot)
RNA_def_enum(ot->srna, "type", move_type_items, LINE_BEGIN, "Type", "Where to move cursor to");
}
-/******************* move select operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Move Select Operator
+ * \{ */
static int move_select_exec(bContext *C, wmOperator *op)
{
@@ -1264,7 +1307,11 @@ void FONT_OT_move_select(wmOperatorType *ot)
"Where to move cursor to, to make a selection");
}
-/************************* change spacing **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Change Spacing
+ * \{ */
static int change_spacing_exec(bContext *C, wmOperator *op)
{
@@ -1314,7 +1361,11 @@ void FONT_OT_change_spacing(wmOperatorType *ot)
20);
}
-/************************* change character **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Change Character
+ * \{ */
static int change_character_exec(bContext *C, wmOperator *op)
{
@@ -1368,7 +1419,11 @@ void FONT_OT_change_character(wmOperatorType *ot)
255);
}
-/******************* line break operator ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Line Break Operator
+ * \{ */
static int line_break_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -1400,7 +1455,11 @@ void FONT_OT_line_break(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/******************* delete operator **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Operator
+ * \{ */
static const EnumPropertyItem delete_type_items[] = {
{DEL_NEXT_CHAR, "NEXT_CHARACTER", 0, "Next Character", ""},
@@ -1549,7 +1608,11 @@ void FONT_OT_delete(wmOperatorType *ot)
"Which part of the text to delete");
}
-/*********************** insert text operator *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Insert Text Operator
+ * \{ */
static int insert_text_exec(bContext *C, wmOperator *op)
{
@@ -1700,7 +1763,12 @@ void FONT_OT_text_insert(wmOperatorType *ot)
"Next typed character will strike through previous, for special character input");
}
-/*********************** textbox add operator *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Textbox Add Operator
+ * \{ */
+
static int textbox_add_exec(bContext *C, wmOperator *UNUSED(op))
{
Object *obedit = CTX_data_active_object(C);
@@ -1736,7 +1804,11 @@ void FONT_OT_textbox_add(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/*********************** textbox remove operator *************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Textbox Remove Operator
+ * \{ */
static int textbox_remove_exec(bContext *C, wmOperator *op)
{
@@ -1778,7 +1850,11 @@ void FONT_OT_textbox_remove(wmOperatorType *ot)
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "The current text box", 0, INT_MAX);
}
-/***************** editmode enter/exit ********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Editmode Enter/Exit
+ * \{ */
void ED_curve_editfont_make(Object *obedit)
{
@@ -1851,7 +1927,11 @@ void ED_curve_editfont_free(Object *obedit)
BKE_curve_editfont_free((Curve *)obedit->data);
}
-/********************** set case operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Case Operator
+ * \{ */
static const EnumPropertyItem case_items[] = {
{CASE_LOWER, "LOWER", 0, "Lower", ""},
@@ -1920,7 +2000,11 @@ void FONT_OT_case_set(wmOperatorType *ot)
RNA_def_enum(ot->srna, "case", case_items, CASE_LOWER, "Case", "Lower or upper case");
}
-/********************** toggle case operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Case Operator
+ * \{ */
static int toggle_case_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -2031,7 +2115,7 @@ static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)
if (pprop->prop) {
idptr = RNA_property_pointer_get((PointerRNA *)pprop, pprop->prop);
- vfont = idptr.id.data;
+ vfont = (VFont *)idptr.owner_id;
}
path = (vfont && !BKE_vfont_is_builtin(vfont)) ? vfont->name : U.fontdir;
@@ -2071,7 +2155,11 @@ void FONT_OT_open(wmOperatorType *ot)
FILE_SORT_ALPHA);
}
-/******************* delete operator *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Delete Operator
+ * \{ */
static int font_unlink_exec(bContext *C, wmOperator *op)
{
@@ -2190,3 +2278,5 @@ bool ED_curve_editfont_select_pick(
return false;
}
}
+
+/** \} */
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 d23965269ab..fa9c0f1fbb2 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/arrow3d_gizmo.c
@@ -363,8 +363,8 @@ static void gizmo_arrow_exit(bContext *C, wmGizmo *gz, const bool cancel)
const bool is_prop_valid = WM_gizmo_target_property_is_valid(gz_prop);
if (!cancel) {
- /* Assign incase applying the operation needs an updated offset
- * editmesh bisect needs this. */
+ /* Assign in case applying the operation needs an updated offset
+ * edit-mesh bisect needs this. */
if (is_prop_valid) {
const int transform_flag = RNA_enum_get(arrow->gizmo.ptr, "transform");
const bool constrained = (transform_flag & ED_GIZMO_ARROW_XFORM_FLAG_CONSTRAINED) != 0;
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 e2a86469da1..406f76bc65e 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/cage3d_gizmo.c
@@ -358,7 +358,7 @@ static void gizmo_cage3d_draw_intern(
bool show = false;
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. */
+ * otherwise the entire rectangle is the hot-spot. */
if (draw_options & ED_GIZMO_CAGE2D_DRAW_FLAG_XFORM_CENTER_HANDLE) {
show = true;
}
diff --git a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
index 21f779b72b1..37ee95d5058 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/move3d_gizmo.c
@@ -283,6 +283,7 @@ static int gizmo_move_modal(bContext *C,
.use_occlusion_test = true,
},
mval_fl,
+ NULL,
&dist_px,
co,
NULL)) {
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index 07b61751b22..22f1753a810 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -1156,7 +1156,7 @@ static tGPsdata *gp_session_initpaint(bContext *C)
/* create new context data */
p = MEM_callocN(sizeof(tGPsdata), "Annotation Drawing Data");
- /* Try to initialise context data
+ /* Try to initialize context data
* WARNING: This may not always succeed (e.g. using GP in an annotation-only context)
*/
if (gp_session_initdata(C, p) == 0) {
@@ -1252,15 +1252,6 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
/* 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_SCULPT_SETT_FLAG_SELECT_MASK) {
- p->flags |= GP_PAINTFLAG_SELECTMASK;
- }
- }
-
if (has_layer_to_erase == false) {
p->status = GP_STATUS_CAPTURE;
// if (G.debug & G_DEBUG)
diff --git a/source/blender/editors/gpencil/gpencil_add_monkey.c b/source/blender/editors/gpencil/gpencil_add_monkey.c
index c4528518009..139697ad0e3 100644
--- a/source/blender/editors/gpencil/gpencil_add_monkey.c
+++ b/source/blender/editors/gpencil/gpencil_add_monkey.c
@@ -54,7 +54,7 @@ static int gpencil_monkey_color(
short *totcol = give_totcolp(ob);
Material *ma = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
+ ma = BKE_material_gpencil_get(ob, i + 1);
if (STREQ(ma->id.name, pct->name)) {
return i;
}
diff --git a/source/blender/editors/gpencil/gpencil_add_stroke.c b/source/blender/editors/gpencil/gpencil_add_stroke.c
index 80e239c9ae5..74617599eaa 100644
--- a/source/blender/editors/gpencil/gpencil_add_stroke.c
+++ b/source/blender/editors/gpencil/gpencil_add_stroke.c
@@ -53,7 +53,7 @@ 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);
+ ma = BKE_material_gpencil_get(ob, i + 1);
if (STREQ(ma->id.name, pct->name)) {
return i;
}
diff --git a/source/blender/editors/gpencil/gpencil_brush.c b/source/blender/editors/gpencil/gpencil_brush.c
index 9124c0f5d51..d1c4f271321 100644
--- a/source/blender/editors/gpencil/gpencil_brush.c
+++ b/source/blender/editors/gpencil/gpencil_brush.c
@@ -105,6 +105,7 @@ typedef struct tGP_BrushEditData {
eGP_Sculpt_Types brush_type;
eGP_Sculpt_Types brush_type_old;
eGP_Sculpt_Flag flag;
+ eGP_Sculpt_SelectMaskFlag mask;
/* Space Conversion Data */
GP_SpaceConversion gsc;
@@ -133,8 +134,8 @@ typedef struct tGP_BrushEditData {
/* - effect vector (e.g. 2D/3D translation for grab brush) */
float dvec[3];
- /* rotation for derived data */
- float rot;
+ /* rotation for evaluated data */
+ float rot_eval;
/* - multiframe falloff factor */
float mf_falloff;
@@ -300,6 +301,20 @@ static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, c
return influence;
}
+/* Force recal filling data */
+static void gp_recalc_geometry(bGPDstroke *gps)
+{
+ bGPDstroke *gps_orig = gps->runtime.gps_orig;
+ if (gps_orig) {
+ gps_orig->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps_orig->tot_triangles = 0;
+ }
+ else {
+ gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gps->tot_triangles = 0;
+ }
+}
+
/* ************************************************ */
/* Brush Callbacks */
/* This section defines the callbacks used by each brush to perform their magic.
@@ -313,7 +328,7 @@ static float gp_brush_influence_calc(tGP_BrushEditData *gso, const int radius, c
* smooth-brush implementation to test the algorithm for stroke smoothing. */
static bool gp_brush_smooth_apply(tGP_BrushEditData *gso,
bGPDstroke *gps,
- float UNUSED(rot),
+ float UNUSED(rot_eval),
int pt_index,
const int radius,
const int co[2])
@@ -341,7 +356,7 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso,
BKE_gpencil_smooth_stroke_uv(gps, pt_index, inf);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gp_recalc_geometry(gps);
return true;
}
@@ -352,7 +367,7 @@ static bool gp_brush_smooth_apply(tGP_BrushEditData *gso,
/* Make lines thicker or thinner by the specified amounts */
static bool gp_brush_thickness_apply(tGP_BrushEditData *gso,
bGPDstroke *gps,
- float UNUSED(rot),
+ float UNUSED(rot_eval),
int pt_index,
const int radius,
const int co[2])
@@ -396,7 +411,7 @@ static bool gp_brush_thickness_apply(tGP_BrushEditData *gso,
/* Make color more or less transparent by the specified amounts */
static bool gp_brush_strength_apply(tGP_BrushEditData *gso,
bGPDstroke *gps,
- float UNUSED(rot),
+ float UNUSED(rot_eval),
int pt_index,
const int radius,
const int co[2])
@@ -443,7 +458,7 @@ typedef struct tGPSB_Grab_StrokeData {
/* array of influence weights for each of the included points */
float *weights;
/* angles to calc transformation */
- float *rot;
+ float *rot_eval;
/* capacity of the arrays */
int capacity;
@@ -471,7 +486,7 @@ static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps)
memset(data->points, 0, sizeof(int) * data->capacity);
memset(data->weights, 0, sizeof(float) * data->capacity);
- memset(data->rot, 0, sizeof(float) * data->capacity);
+ memset(data->rot_eval, 0, sizeof(float) * data->capacity);
}
else {
/* Create new instance */
@@ -482,7 +497,7 @@ static void gp_brush_grab_stroke_init(tGP_BrushEditData *gso, bGPDstroke *gps)
data->points = MEM_callocN(sizeof(int) * data->capacity, "GP Stroke Grab Indices");
data->weights = MEM_callocN(sizeof(float) * data->capacity, "GP Stroke Grab Weights");
- data->rot = MEM_callocN(sizeof(float) * data->capacity, "GP Stroke Grab X");
+ data->rot_eval = MEM_callocN(sizeof(float) * data->capacity, "GP Stroke Grab Rotations");
/* hook up to the cache */
BLI_ghash_insert(gso->stroke_customdata, gps, data);
@@ -492,7 +507,7 @@ 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,
- float rot,
+ float rot_eval,
int pt_index,
const int radius,
const int co[2])
@@ -506,7 +521,7 @@ static bool gp_brush_grab_store_points(tGP_BrushEditData *gso,
/* insert this point into the set of affected points */
data->points[data->size] = pt_index;
data->weights[data->size] = inf;
- data->rot[data->size] = rot;
+ data->rot_eval[data->size] = rot_eval;
data->size++;
/* done */
@@ -530,10 +545,10 @@ static void gp_brush_grab_calc_dvec(tGP_BrushEditData *gso)
mval_f[0] = (float)(gso->mval[0] - gso->mval_prev[0]);
mval_f[1] = (float)(gso->mval[1] - gso->mval_prev[1]);
- /* apply derived data transformation */
- if (gso->rot != 0.0f) {
- const float cval = cos(gso->rot);
- const float sval = sin(gso->rot);
+ /* apply evaluated data transformation */
+ if (gso->rot_eval != 0.0f) {
+ const float cval = cos(gso->rot_eval);
+ const float sval = sin(gso->rot_eval);
float r[2];
r[0] = (mval_f[0] * cval) - (mval_f[1] * sval);
r[1] = (mval_f[0] * sval) + (mval_f[1] * cval);
@@ -564,8 +579,8 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso,
bGPDspoint *pt = &gps->points[data->points[i]];
float delta[3] = {0.0f};
- /* get derived transformation */
- gso->rot = data->rot[i];
+ /* get evaluated transformation */
+ gso->rot_eval = data->rot_eval[i];
gp_brush_grab_calc_dvec(gso);
/* adjust the amount of displacement to apply */
@@ -586,7 +601,7 @@ static void gp_brush_grab_apply_cached(tGP_BrushEditData *gso,
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gp_recalc_geometry(gps);
}
/* free customdata used for handling this stroke */
@@ -597,7 +612,7 @@ static void gp_brush_grab_stroke_free(void *ptr)
/* free arrays */
MEM_SAFE_FREE(data->points);
MEM_SAFE_FREE(data->weights);
- MEM_SAFE_FREE(data->rot);
+ MEM_SAFE_FREE(data->rot_eval);
/* ... and this item itself, since it was also allocated */
MEM_freeN(data);
@@ -608,7 +623,7 @@ static void gp_brush_grab_stroke_free(void *ptr)
/* NOTE: Depends on gp_brush_grab_calc_dvec() */
static bool gp_brush_push_apply(tGP_BrushEditData *gso,
bGPDstroke *gps,
- float UNUSED(rot),
+ float UNUSED(rot_eval),
int pt_index,
const int radius,
const int co[2])
@@ -676,7 +691,7 @@ 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,
- float UNUSED(rot),
+ float UNUSED(rot_eval),
int pt_index,
const int radius,
const int co[2])
@@ -721,7 +736,7 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso,
/* compute lock axis */
gpsculpt_compute_lock_axis(gso, pt, save_pt);
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gp_recalc_geometry(gps);
/* done */
return true;
@@ -735,7 +750,7 @@ static bool gp_brush_pinch_apply(tGP_BrushEditData *gso,
static bool gp_brush_twist_apply(tGP_BrushEditData *gso,
bGPDstroke *gps,
- float UNUSED(rot),
+ float UNUSED(rot_eval),
int pt_index,
const int radius,
const int co[2])
@@ -809,7 +824,7 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso,
}
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gp_recalc_geometry(gps);
/* done */
return true;
@@ -820,7 +835,7 @@ static bool gp_brush_twist_apply(tGP_BrushEditData *gso,
/* Apply some random jitter to the point */
static bool gp_brush_randomize_apply(tGP_BrushEditData *gso,
bGPDstroke *gps,
- float UNUSED(rot),
+ float UNUSED(rot_eval),
int pt_index,
const int radius,
const int co[2])
@@ -929,7 +944,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso,
CLAMP(pt->uv_rot, -M_PI_2, M_PI_2);
}
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
+ gp_recalc_geometry(gps);
/* done */
return true;
@@ -939,7 +954,7 @@ static bool gp_brush_randomize_apply(tGP_BrushEditData *gso,
/* Change weight paint for vertex groups */
static bool gp_brush_weight_apply(tGP_BrushEditData *gso,
bGPDstroke *gps,
- float UNUSED(rot),
+ float UNUSED(rot_eval),
int pt_index,
const int radius,
const int co[2])
@@ -1175,7 +1190,7 @@ static void gp_brush_clone_adjust(tGP_BrushEditData *gso)
size_t snum;
/* Compute the amount of movement to apply (overwrites dvec) */
- gso->rot = 0.0f;
+ gso->rot_eval = 0.0f;
gp_brush_grab_calc_dvec(gso);
/* For each of the stored strokes, apply the offset to each point */
@@ -1323,6 +1338,9 @@ static bool gpsculpt_brush_init(bContext *C, wmOperator *op)
gso->sa = CTX_wm_area(C);
gso->ar = CTX_wm_region(C);
+ /* save mask */
+ gso->mask = ts->gpencil_selectmode_sculpt;
+
/* multiframe settings */
gso->is_multiframe = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gso->gpd);
gso->use_multiframe_falloff = (ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_FRAME_FALLOFF) != 0;
@@ -1486,35 +1504,38 @@ static void gpsculpt_brush_init_stroke(tGP_BrushEditData *gso)
/* Apply ----------------------------------------------- */
-/* Get angle of the segment relative to the original segment before any transformation */
-static float gpsculpt_transform_rot_get(GP_SpaceConversion *gsc,
- bGPDstroke *gps_derived,
- bGPDspoint *pt_derived,
- int idx_derived)
+/* Get angle of the segment relative to the original segment before any transformation
+ * For strokes with one point only this is impossible to calculate because there isn't a
+ * valid reference point.
+ */
+static float gpsculpt_rotation_eval_get(GP_SpaceConversion *gsc,
+ bGPDstroke *gps_eval,
+ bGPDspoint *pt_eval,
+ int idx_eval)
{
- bGPDstroke *gps_orig = gps_derived->runtime.gps_orig;
- bGPDspoint *pt_orig = &gps_orig->points[pt_derived->runtime.idx_orig];
- bGPDspoint *pt_derived_prev = NULL;
+ bGPDstroke *gps_orig = gps_eval->runtime.gps_orig;
+ bGPDspoint *pt_orig = &gps_orig->points[pt_eval->runtime.idx_orig];
+ bGPDspoint *pt_prev_eval = NULL;
bGPDspoint *pt_orig_prev = NULL;
- if (idx_derived != 0) {
- pt_derived_prev = &gps_derived->points[idx_derived - 1];
+ if (idx_eval != 0) {
+ pt_prev_eval = &gps_eval->points[idx_eval - 1];
}
else {
- if (gps_derived->totpoints > 1) {
- pt_derived_prev = &gps_derived->points[idx_derived + 1];
+ if (gps_eval->totpoints > 1) {
+ pt_prev_eval = &gps_eval->points[idx_eval + 1];
}
else {
return 0.0f;
}
}
- if (pt_derived->runtime.idx_orig != 0) {
- pt_orig_prev = &gps_orig->points[pt_derived->runtime.idx_orig - 1];
+ if (pt_eval->runtime.idx_orig != 0) {
+ pt_orig_prev = &gps_orig->points[pt_eval->runtime.idx_orig - 1];
}
else {
if (gps_orig->totpoints > 1) {
- pt_orig_prev = &gps_orig->points[pt_derived->runtime.idx_orig + 1];
+ pt_orig_prev = &gps_orig->points[pt_eval->runtime.idx_orig + 1];
}
else {
return 0.0f;
@@ -1522,17 +1543,17 @@ static float gpsculpt_transform_rot_get(GP_SpaceConversion *gsc,
}
/* create 2D vectors of the stroke segments */
- float v_orig_a[2], v_orig_b[2], v_derived_a[2], v_derived_b[2];
+ float v_orig_a[2], v_orig_b[2], v_eval_a[2], v_eval_b[2];
gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_orig->x, v_orig_a);
gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_orig_prev->x, v_orig_b);
sub_v2_v2(v_orig_a, v_orig_b);
- gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_derived->x, v_derived_a);
- gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_derived_prev->x, v_derived_b);
- sub_v2_v2(v_derived_a, v_derived_b);
+ gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_eval->x, v_eval_a);
+ gp_point_3d_to_xy(gsc, GP_STROKE_3DSPACE, &pt_prev_eval->x, v_eval_b);
+ sub_v2_v2(v_eval_a, v_eval_b);
- return angle_v2v2(v_orig_a, v_derived_a);
+ return angle_v2v2(v_orig_a, v_eval_a);
}
/* Apply brush operation to points in this stroke */
@@ -1555,7 +1576,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
int i;
bool include_last = false;
bool changed = false;
- float rot = 0.0f;
+ float rot_eval = 0.0f;
if (gps->totpoints == 1) {
bGPDspoint pt_temp;
pt = &gps->points[0];
@@ -1570,8 +1591,8 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
if (len_v2v2_int(mval_i, pc1) <= radius) {
/* apply operation to this point */
if (pt->runtime.pt_orig != NULL) {
- rot = gpsculpt_transform_rot_get(&gso->gsc, gps, pt, 0);
- changed = apply(gso, gps->runtime.gps_orig, rot, pt->runtime.idx_orig, radius, pc1);
+ rot_eval = gpsculpt_rotation_eval_get(&gso->gsc, gps, pt, 0);
+ changed = apply(gso, gps->runtime.gps_orig, rot_eval, pt->runtime.idx_orig, radius, pc1);
}
}
}
@@ -1587,7 +1608,7 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
/* Skip if neither one is selected
* (and we are only allowed to edit/consider selected points) */
- if ((gso->settings->flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) && (!gso->is_weight_mode)) {
+ if ((GPENCIL_ANY_SCULPT_MASK(gso->mask)) && (!gso->is_weight_mode)) {
if (!(pt1->flag & GP_SPOINT_SELECT) && !(pt2->flag & GP_SPOINT_SELECT)) {
include_last = false;
continue;
@@ -1615,8 +1636,8 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
/* To each point individually... */
pt = &gps->points[i];
if (pt->runtime.pt_orig != NULL) {
- rot = gpsculpt_transform_rot_get(&gso->gsc, gps, pt, i);
- ok = apply(gso, gps->runtime.gps_orig, rot, pt->runtime.idx_orig, radius, pc1);
+ rot_eval = gpsculpt_rotation_eval_get(&gso->gsc, gps, pt, i);
+ ok = apply(gso, gps->runtime.gps_orig, rot_eval, pt->runtime.idx_orig, radius, pc1);
}
/* Only do the second point if this is the last segment,
@@ -1630,8 +1651,8 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
if (i + 1 == gps->totpoints - 1) {
pt = &gps->points[i + 1];
if (pt->runtime.pt_orig != NULL) {
- rot = gpsculpt_transform_rot_get(&gso->gsc, gps, pt, i + 1);
- ok |= apply(gso, gps->runtime.gps_orig, rot, pt->runtime.idx_orig, radius, pc2);
+ rot_eval = gpsculpt_rotation_eval_get(&gso->gsc, gps, pt, i + 1);
+ ok |= apply(gso, gps->runtime.gps_orig, rot_eval, pt->runtime.idx_orig, radius, pc2);
include_last = false;
}
}
@@ -1649,8 +1670,9 @@ static bool gpsculpt_brush_do_stroke(tGP_BrushEditData *gso,
*/
pt = &gps->points[i];
if (pt->runtime.pt_orig != NULL) {
- rot = gpsculpt_transform_rot_get(&gso->gsc, gps, pt, i);
- changed |= apply(gso, gps->runtime.gps_orig, rot, pt->runtime.idx_orig, radius, pc1);
+ rot_eval = gpsculpt_rotation_eval_get(&gso->gsc, gps, pt, i);
+ changed |= apply(
+ gso, gps->runtime.gps_orig, rot_eval, pt->runtime.idx_orig, radius, pc1);
include_last = false;
}
}
@@ -1752,10 +1774,7 @@ static bool gpsculpt_brush_do_frame(
break;
}
/* Triangulation must be calculated if changed */
- if (changed) {
- gps->flag |= GP_STROKE_RECALC_GEOMETRY;
- gps->tot_triangles = 0;
- }
+ gp_recalc_geometry(gps);
}
return changed;
@@ -1777,7 +1796,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
case GP_SCULPT_TYPE_PUSH: /* Push points */
{
/* calculate amount of displacement to apply */
- gso->rot = 0.0f;
+ gso->rot_eval = 0.0f;
gp_brush_grab_calc_dvec(gso);
break;
}
@@ -1793,7 +1812,7 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
case GP_SCULPT_TYPE_RANDOMIZE: /* Random jitter */
{
/* compute the displacement vector for the cursor (in data space) */
- gso->rot = 0.0f;
+ gso->rot_eval = 0.0f;
gp_brush_grab_calc_dvec(gso);
break;
}
@@ -1808,10 +1827,10 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
if (gpl->actframe == NULL) {
continue;
}
- /* Get derived frames array data */
- int derived_idx = BLI_findindex(&gpd->layers, gpl);
- bGPDframe *derived_gpf = &ob_eval->runtime.derived_frames[derived_idx];
- if (derived_gpf == NULL) {
+ /* Get evaluated frames array data */
+ int idx_eval = BLI_findindex(&gpd->layers, gpl);
+ bGPDframe *gpf_eval = &ob_eval->runtime.gpencil_evaluated_frames[idx_eval];
+ if (gpf_eval == NULL) {
continue;
}
@@ -1845,14 +1864,14 @@ static bool gpsculpt_brush_apply_standard(bContext *C, tGP_BrushEditData *gso)
/* affect strokes in this frame */
changed |= gpsculpt_brush_do_frame(
- C, gso, gpl, (gpf == gpl->actframe) ? derived_gpf : gpf, diff_mat);
+ C, gso, gpl, (gpf == gpl->actframe) ? gpf_eval : gpf, diff_mat);
}
}
}
else {
/* Apply to active frame's strokes */
gso->mf_falloff = 1.0f;
- changed |= gpsculpt_brush_do_frame(C, gso, gpl, derived_gpf, diff_mat);
+ changed |= gpsculpt_brush_do_frame(C, gso, gpl, gpf_eval, diff_mat);
}
}
CTX_DATA_END;
diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c
index 0928913aad5..e763eec1b0d 100644
--- a/source/blender/editors/gpencil/gpencil_data.c
+++ b/source/blender/editors/gpencil/gpencil_data.c
@@ -105,7 +105,7 @@ static bool gp_data_add_poll(bContext *C)
/* add new datablock - wrapper around API */
static int gp_data_add_exec(bContext *C, wmOperator *op)
{
- PointerRNA gpd_owner = {{NULL}};
+ 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);
@@ -231,7 +231,7 @@ void GPENCIL_OT_data_unlink(wmOperatorType *ot)
/* add new layer - wrapper around API */
static int gp_layer_add_exec(bContext *C, wmOperator *op)
{
- PointerRNA gpd_owner = {{NULL}};
+ 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);
@@ -538,10 +538,12 @@ static int gp_layer_duplicate_object_exec(bContext *C, wmOperator *op)
* otherwise add the slot with the material
*/
Material *ma_src = give_current_material(ob_src, gps_src->mat_nr + 1);
- int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
+ if (ma_src != NULL) {
+ int idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
- /* Reassign the stroke material to the right slot in destination object. */
- gps_dst->mat_nr = idx;
+ /* Reassign the stroke material to the right slot in destination object. */
+ gps_dst->mat_nr = idx;
+ }
/* add new stroke to frame */
BLI_addtail(&gpf_dst->strokes, gps_dst);
@@ -840,6 +842,10 @@ static int gp_hide_exec(bContext *C, wmOperator *op)
if (gpl != layer) {
gpl->flag |= GP_LAYER_HIDE;
}
+ else {
+ /* Be sure the active layer is unhidden. */
+ gpl->flag &= ~GP_LAYER_HIDE;
+ }
}
}
else {
@@ -1419,7 +1425,7 @@ static int gp_stroke_change_color_exec(bContext *C, wmOperator *op)
bGPdata *gpd = ED_gpencil_data_get_active(C);
Object *ob = CTX_data_active_object(C);
if (name[0] == '\0') {
- ma = give_current_material(ob, ob->actcol);
+ ma = BKE_material_gpencil_get(ob, ob->actcol);
}
else {
ma = (Material *)BKE_libblock_find_name(bmain, ID_MA, name);
@@ -1539,9 +1545,10 @@ static int gp_stroke_lock_color_exec(bContext *C, wmOperator *UNUSED(op))
}
/* unlock color */
Material *tmp_ma = give_current_material(ob, gps->mat_nr + 1);
-
- tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
- DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
+ if (tmp_ma) {
+ tmp_ma->gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
+ DEG_id_tag_update(&tmp_ma->id, ID_RECALC_COPY_ON_WRITE);
+ }
}
}
}
@@ -2291,7 +2298,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
short *totcol = give_totcolp(ob_src);
for (short i = 0; i < *totcol; i++) {
- Material *tmp_ma = give_current_material(ob_src, i + 1);
+ Material *tmp_ma = BKE_material_gpencil_get(ob_src, i + 1);
BKE_gpencil_object_material_ensure(bmain, ob_dst, tmp_ma);
}
@@ -2325,7 +2332,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op)
for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) {
/* Reassign material. Look old material and try to find in destination. */
- ma_src = give_current_material(ob_src, gps->mat_nr + 1);
+ ma_src = BKE_material_gpencil_get(ob_src, gps->mat_nr + 1);
gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma_src);
bGPDspoint *pt;
@@ -2433,7 +2440,7 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
}
for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
+ ma = BKE_material_gpencil_get(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
gp_style->flag |= GP_STYLE_COLOR_LOCKED;
@@ -2453,7 +2460,7 @@ static int gpencil_lock_layer_exec(bContext *C, wmOperator *UNUSED(op))
continue;
}
- ma = give_current_material(ob, gps->mat_nr + 1);
+ ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
DEG_id_tag_update(&ma->id, ID_RECALC_COPY_ON_WRITE);
gp_style = ma->gp_style;
@@ -2496,7 +2503,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Object *ob = CTX_data_active_object(C);
- Material *active_ma = give_current_material(ob, ob->actcol);
+ Material *active_ma = BKE_material_gpencil_get(ob, ob->actcol);
MaterialGPencilStyle *active_color = BKE_material_gpencil_settings_get(ob, ob->actcol);
MaterialGPencilStyle *gp_style;
@@ -2516,7 +2523,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
Material *ma = NULL;
short *totcol = give_totcolp(ob);
for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
+ ma = BKE_material_gpencil_get(ob, i + 1);
/* Skip if this is the active one */
if ((ma == NULL) || (ma == active_ma)) {
continue;
@@ -2536,7 +2543,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
if (isolate) {
/* Set flags on all "other" colors */
for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
+ ma = BKE_material_gpencil_get(ob, i + 1);
if (ma == NULL) {
continue;
}
@@ -2553,7 +2560,7 @@ static int gpencil_color_isolate_exec(bContext *C, wmOperator *op)
else {
/* Clear flags - Restore everything else */
for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
+ ma = BKE_material_gpencil_get(ob, i + 1);
if (ma == NULL) {
continue;
}
@@ -2618,7 +2625,7 @@ static int gpencil_color_hide_exec(bContext *C, wmOperator *op)
/* hide unselected */
MaterialGPencilStyle *color = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
+ ma = BKE_material_gpencil_get(ob, i + 1);
if (ma) {
color = ma->gp_style;
if (active_color != color) {
@@ -2681,7 +2688,7 @@ static int gpencil_color_reveal_exec(bContext *C, wmOperator *UNUSED(op))
MaterialGPencilStyle *gp_style = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
+ ma = BKE_material_gpencil_get(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
gp_style->flag &= ~GP_STYLE_COLOR_HIDE;
@@ -2734,7 +2741,7 @@ static int gpencil_color_lock_all_exec(bContext *C, wmOperator *UNUSED(op))
MaterialGPencilStyle *gp_style = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
+ ma = BKE_material_gpencil_get(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
gp_style->flag |= GP_STYLE_COLOR_LOCKED;
@@ -2787,7 +2794,7 @@ static int gpencil_color_unlock_all_exec(bContext *C, wmOperator *UNUSED(op))
MaterialGPencilStyle *gp_style = NULL;
for (short i = 0; i < *totcol; i++) {
- ma = give_current_material(ob, i + 1);
+ ma = BKE_material_gpencil_get(ob, i + 1);
if (ma) {
gp_style = ma->gp_style;
gp_style->flag &= ~GP_STYLE_COLOR_LOCKED;
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index cc229fcb383..12b3792e36e 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -222,6 +222,17 @@ void GPENCIL_OT_editmode_toggle(wmOperatorType *ot)
}
/* set select mode */
+static bool gpencil_selectmode_toggle_poll(bContext *C)
+{
+ /* edit only supported with grease pencil objects */
+ Object *ob = CTX_data_active_object(C);
+ if ((ob == NULL) || (ob->type != OB_GPENCIL) || (ob->mode != OB_MODE_EDIT_GPENCIL)) {
+ return false;
+ }
+
+ return ED_operator_view3d_active(C);
+}
+
static int gpencil_selectmode_toggle_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
@@ -229,7 +240,7 @@ static int gpencil_selectmode_toggle_exec(bContext *C, wmOperator *op)
const int mode = RNA_int_get(op->ptr, "mode");
/* Just set mode */
- ts->gpencil_selectmode = mode;
+ ts->gpencil_selectmode_edit = mode;
WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
@@ -248,7 +259,7 @@ void GPENCIL_OT_selectmode_toggle(wmOperatorType *ot)
/* callbacks */
ot->exec = gpencil_selectmode_toggle_exec;
- ot->poll = gp_strokes_edit3d_poll;
+ ot->poll = gpencil_selectmode_toggle_poll;
/* flags */
ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER;
@@ -1180,10 +1191,15 @@ static int gp_strokes_copy_exec(bContext *C, wmOperator *op)
GHash *ma_to_name = gp_strokes_copypastebuf_colors_material_to_name_create(bmain);
for (bGPDstroke *gps = gp_strokes_copypastebuf.first; gps; gps = gps->next) {
if (ED_gpencil_stroke_can_use(C, gps)) {
+ Material *ma = give_current_material(ob, gps->mat_nr + 1);
+ /* Avoid default material. */
+ if (ma == NULL) {
+ continue;
+ }
+
char **ma_name_val;
if (!BLI_ghash_ensure_p(
gp_strokes_copypastebuf_colors, &gps->mat_nr, (void ***)&ma_name_val)) {
- Material *ma = give_current_material(ob, gps->mat_nr + 1);
char *ma_name = BLI_ghash_lookup(ma_to_name, ma);
*ma_name_val = MEM_dupallocN(ma_name);
}
@@ -1230,8 +1246,8 @@ static bool gp_strokes_paste_poll(bContext *C)
}
typedef enum eGP_PasteMode {
- GP_COPY_ONLY = -1,
- GP_COPY_MERGE = 1,
+ GP_COPY_BY_LAYER = -1,
+ GP_COPY_TO_ACTIVE = 1,
} eGP_PasteMode;
static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
@@ -1264,7 +1280,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
/* no active layer - let's just create one */
gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
}
- else if ((gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_MERGE)) {
+ else if ((gpencil_layer_is_editable(gpl) == false) && (type == GP_COPY_TO_ACTIVE)) {
BKE_report(
op->reports, RPT_ERROR, "Can not paste strokes when active layer is hidden or locked");
return OPERATOR_CANCELLED;
@@ -1317,7 +1333,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
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) {
+ if (type != GP_COPY_TO_ACTIVE) {
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) */
@@ -1350,7 +1366,7 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
/* Remap material */
Material *ma = BLI_ghash_lookup(new_colors, POINTER_FROM_INT(new_stroke->mat_nr));
new_stroke->mat_nr = BKE_gpencil_object_material_get_index(ob, ma);
- BLI_assert(new_stroke->mat_nr >= 0); /* have to add the material first */
+ CLAMP_MIN(new_stroke->mat_nr, 0);
}
}
}
@@ -1368,15 +1384,15 @@ static int gp_strokes_paste_exec(bContext *C, wmOperator *op)
void GPENCIL_OT_paste(wmOperatorType *ot)
{
static const EnumPropertyItem copy_type[] = {
- {GP_COPY_ONLY, "COPY", 0, "Copy", ""},
- {GP_COPY_MERGE, "MERGE", 0, "Merge", ""},
+ {GP_COPY_TO_ACTIVE, "ACTIVE", 0, "Paste to Active", ""},
+ {GP_COPY_BY_LAYER, "LAYER", 0, "Paste by Layer", ""},
{0, NULL, 0, NULL, NULL},
};
/* identifiers */
ot->name = "Paste Strokes";
ot->idname = "GPENCIL_OT_paste";
- ot->description = "Paste previously copied strokes or copy and merge in active layer";
+ ot->description = "Paste previously copied strokes to active layer or to original layer";
/* callbacks */
ot->exec = gp_strokes_paste_exec;
@@ -1386,33 +1402,18 @@ void GPENCIL_OT_paste(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- ot->prop = RNA_def_enum(ot->srna, "type", copy_type, 0, "Type", "");
+ ot->prop = RNA_def_enum(ot->srna, "type", copy_type, GP_COPY_TO_ACTIVE, "Type", "");
}
/* ******************* Move To Layer ****************************** */
-static int gp_move_to_layer_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_move_to_layer", "layer");
- UI_popup_menu_end(C, pup);
-
- return OPERATOR_INTERFACE;
-}
-
-// FIXME: allow moving partial strokes
static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = CTX_data_gpencil_data(C);
Scene *scene = CTX_data_scene(C);
bGPDlayer *target_layer = NULL;
ListBase strokes = {NULL, NULL};
- int layer_num = RNA_enum_get(op->ptr, "layer");
+ int layer_num = RNA_int_get(op->ptr, "layer");
const bool use_autolock = (bool)(gpd->flag & GP_DATA_AUTOLOCK_LAYERS);
if (GPENCIL_MULTIEDIT_SESSIONS_ON(gpd)) {
@@ -1425,23 +1426,16 @@ static int gp_move_to_layer_exec(bContext *C, wmOperator *op)
gpd->flag &= ~GP_DATA_AUTOLOCK_LAYERS;
}
- /* Get layer or create new one */
- if (layer_num == -1) {
- /* Create layer */
- target_layer = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true);
- }
- else {
- /* Try to get layer */
- target_layer = BLI_findlink(&gpd->layers, layer_num);
+ /* Try to get layer */
+ target_layer = BLI_findlink(&gpd->layers, layer_num);
- if (target_layer == NULL) {
- /* back autolock status */
- if (use_autolock) {
- gpd->flag |= GP_DATA_AUTOLOCK_LAYERS;
- }
- BKE_reportf(op->reports, RPT_ERROR, "There is no layer number %d", layer_num);
- return OPERATOR_CANCELLED;
+ if (target_layer == NULL) {
+ /* back autolock status */
+ if (use_autolock) {
+ gpd->flag |= GP_DATA_AUTOLOCK_LAYERS;
}
+ BKE_reportf(op->reports, RPT_ERROR, "There is no layer number %d", layer_num);
+ return OPERATOR_CANCELLED;
}
/* Extract all strokes to move to this layer
@@ -1509,16 +1503,14 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot)
"Move selected strokes to another layer"; // XXX: allow moving individual points too?
/* callbacks */
- ot->invoke = gp_move_to_layer_invoke;
ot->exec = gp_move_to_layer_exec;
ot->poll = gp_stroke_edit_poll; // XXX?
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* gp layer to use (dynamic enum) */
- ot->prop = RNA_def_enum(ot->srna, "layer", DummyRNA_DEFAULT_items, 0, "Grease Pencil Layer", "");
- RNA_def_enum_funcs(ot->prop, ED_gpencil_layers_with_new_enum_itemf);
+ /* GPencil layer to use. */
+ ot->prop = RNA_def_int(ot->srna, "layer", 0, 0, INT_MAX, "Grease Pencil Layer", "", 0, INT_MAX);
}
/* ********************* Add Blank Frame *************************** */
@@ -3333,7 +3325,7 @@ typedef enum eGP_ReprojectModes {
GP_REPROJECT_FRONT = 0,
GP_REPROJECT_SIDE,
GP_REPROJECT_TOP,
- /* On same plane, parallel to viewplane */
+ /* On same plane, parallel to view-plane. */
GP_REPROJECT_VIEW,
/* Reprojected on to the scene geometry */
GP_REPROJECT_SURFACE,
@@ -3344,11 +3336,14 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
Scene *scene = CTX_data_scene(C);
+ Main *bmain = CTX_data_main(C);
ToolSettings *ts = CTX_data_tool_settings(C);
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
Object *ob = CTX_data_active_object(C);
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ar->regiondata;
+ SnapObjectContext *sctx = NULL;
+ int oldframe = (int)DEG_get_ctime(depsgraph);
GP_SpaceConversion gsc = {NULL};
eGP_ReprojectModes mode = RNA_enum_get(op->ptr, "type");
@@ -3358,28 +3353,33 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
/* init space conversion stuff */
gp_point_conversion_init(C, &gsc);
- /* init autodist for geometry projection */
- if (mode == GP_REPROJECT_SURFACE) {
- view3d_region_operator_needs_opengl(CTX_wm_window(C), gsc.ar);
- ED_view3d_autodist_init(depsgraph, gsc.ar, CTX_wm_view3d(C), 0);
- }
-
- // TODO: For deforming geometry workflow, create new frames?
+ int cfra_prv = INT_MIN;
+ /* init snap context for geometry projection */
+ sctx = ED_transform_snap_object_context_create_view3d(
+ bmain, scene, depsgraph, 0, ar, CTX_wm_view3d(C));
/* Go through each editable + selected stroke, adjusting each of its points one by one... */
GP_EDITABLE_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
if (gps->flag & GP_STROKE_SELECT) {
+
+ /* update frame to get the new location of objects */
+ if ((mode == GP_REPROJECT_SURFACE) && (cfra_prv != gpf_->framenum)) {
+ cfra_prv = gpf_->framenum;
+ CFRA = gpf_->framenum;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+ }
+
bGPDspoint *pt;
int i;
/* Adjust each point */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
float xy[2];
- /* 3D to Screenspace */
- /* Note: We can't use gp_point_to_xy() here because that uses ints for the screenspace
- * coordinates, resulting in lost precision, which in turn causes stairstepping
- * artifacts in the final points.
- */
+ /* 3D to Screen-space */
+ /* Note: We can't use gp_point_to_xy() here because that uses ints for the screen-space
+ * coordinates, resulting in lost precision, which in turn causes stair-stepping
+ * artifacts in the final points. */
+
bGPDspoint pt2;
gp_point_to_parent_space(pt, gpstroke_iter.diff_mat, &pt2);
gp_point_to_xy_fl(&gsc, gps, &pt2, &xy[0], &xy[1]);
@@ -3428,26 +3428,34 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
/* 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
- */
+ /* Project screen-space back to 3D space (from current perspective)
+ * so that all points have been treated the same way. */
else if (mode == GP_REPROJECT_VIEW) {
- /* Planar - All on same plane parallel to the viewplane */
+ /* Planar - All on same plane parallel to the view-plane. */
gp_point_xy_to_3d(&gsc, scene, xy, &pt->x);
}
else {
/* Geometry - Snap to surfaces of visible geometry */
- /* XXX: There will be precision loss (possible stairstep artifacts)
- * from this conversion to satisfy the API's */
- const int screen_co[2] = {(int)xy[0], (int)xy[1]};
-
- int depth_margin = 0; // XXX: 4 for strokes, 0 for normal
- float depth;
-
- /* XXX: The proper procedure computes the depths into an array,
- * to have smooth transitions when all else fails... */
- if (ED_view3d_autodist_depth(gsc.ar, screen_co, depth_margin, &depth)) {
- ED_view3d_autodist_simple(gsc.ar, screen_co, &pt->x, 0, &depth);
+ float ray_start[3];
+ float ray_normal[3];
+ /* magic value for initial depth copied from the default
+ * value of Python's Scene.ray_cast function
+ */
+ float depth = 1.70141e+38f;
+ float location[3] = {0.0f, 0.0f, 0.0f};
+ float normal[3] = {0.0f, 0.0f, 0.0f};
+
+ ED_view3d_win_to_ray(ar, xy, &ray_start[0], &ray_normal[0]);
+ if (ED_transform_snap_object_project_ray(sctx,
+ &(const struct SnapObjectParams){
+ .snap_select = SNAP_ALL,
+ },
+ &ray_start[0],
+ &ray_normal[0],
+ &depth,
+ &location[0],
+ &normal[0])) {
+ copy_v3_v3(&pt->x, location);
}
else {
/* Default to planar */
@@ -3464,6 +3472,15 @@ static int gp_strokes_reproject_exec(bContext *C, wmOperator *op)
}
GP_EDITABLE_STROKES_END(gpstroke_iter);
+ /* return frame state and DB to original state */
+ CFRA = oldframe;
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
+
+ if (sctx != NULL) {
+ ED_transform_snap_object_context_destroy(sctx);
+ }
+
+ /* update changed data */
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
return OPERATOR_FINISHED;
@@ -3549,7 +3566,7 @@ static void gp_smooth_stroke(bContext *C, wmOperator *op)
}
if (smooth_thickness) {
/* thickness need to repeat process several times */
- for (int r2 = 0; r2 < r * 10; r2++) {
+ for (int r2 = 0; r2 < r * 20; r2++) {
BKE_gpencil_smooth_stroke_thickness(gps, i, factor);
}
}
@@ -4055,7 +4072,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
/* add duplicate materials */
/* XXX same material can be in multiple slots. */
- ma = give_current_material(ob, gps->mat_nr + 1);
+ ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
idx = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma);
@@ -4128,7 +4145,7 @@ static int gp_stroke_separate_exec(bContext *C, wmOperator *op)
if (ED_gpencil_stroke_can_use(C, gps) == false) {
continue;
}
- ma = give_current_material(ob, gps->mat_nr + 1);
+ ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
gps->mat_nr = BKE_gpencil_object_material_ensure(bmain, ob_dst, ma);
}
}
@@ -4305,7 +4322,7 @@ void GPENCIL_OT_stroke_smooth(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- prop = RNA_def_int(ot->srna, "repeat", 1, 1, 10, "Repeat", "", 1, 5);
+ prop = RNA_def_int(ot->srna, "repeat", 1, 1, 50, "Repeat", "", 1, 20);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
RNA_def_float(ot->srna, "factor", 0.5f, 0.0f, 2.0f, "Factor", "", 0.0f, 2.0f);
@@ -4441,7 +4458,7 @@ static int gpencil_cutter_lasso_select(bContext *C,
if ((pt->flag & GP_SPOINT_SELECT) || (pt->flag & GP_SPOINT_TAG)) {
continue;
}
- /* convert point coords to screenspace */
+ /* convert point coords to screen-space */
const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
if (is_inside) {
tot_inside++;
diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c
index 5637e755198..372973e1040 100644
--- a/source/blender/editors/gpencil/gpencil_fill.c
+++ b/source/blender/editors/gpencil/gpencil_fill.c
@@ -48,6 +48,7 @@
#include "BKE_context.h"
#include "BKE_screen.h"
#include "BKE_paint.h"
+#include "BKE_report.h"
#include "ED_gpencil.h"
#include "ED_screen.h"
@@ -1038,7 +1039,15 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf)
gps->flag |= GP_STROKE_CYCLIC;
gps->flag |= GP_STROKE_3DSPACE;
- gps->mat_nr = BKE_gpencil_object_material_ensure(tgpf->bmain, tgpf->ob, tgpf->mat);
+ gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(tgpf->ob, brush);
+ if (gps->mat_nr < 0) {
+ if (tgpf->ob->actcol - 1 < 0) {
+ gps->mat_nr = 0;
+ }
+ else {
+ gps->mat_nr = tgpf->ob->actcol - 1;
+ }
+ }
/* allocate memory for storage points */
gps->totpoints = tgpf->sbuffer_used;
@@ -1346,8 +1355,28 @@ static int gpencil_fill_init(bContext *C, wmOperator *op)
/* start of interactive part of operator */
static int gpencil_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
+ Object *ob = CTX_data_active_object(C);
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ Brush *brush = BKE_paint_brush(&ts->gp_paint->paint);
tGPDfill *tgpf = NULL;
+ /* Fill tool needs a material (cannot use default material) */
+ bool valid = true;
+ if ((brush) && (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED)) {
+ if (brush->gpencil_settings->material == NULL) {
+ valid = false;
+ }
+ }
+ else {
+ if (give_current_material(ob, ob->actcol) == NULL) {
+ valid = false;
+ }
+ }
+ if (!valid) {
+ BKE_report(op->reports, RPT_ERROR, "Fill tool needs active material.");
+ return OPERATOR_CANCELLED;
+ }
+
/* try to initialize context data needed */
if (!gpencil_fill_init(C, op)) {
gpencil_fill_exit(C, op);
diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h
index 7f36eb50802..f7fc7e34460 100644
--- a/source/blender/editors/gpencil/gpencil_intern.h
+++ b/source/blender/editors/gpencil/gpencil_intern.h
@@ -637,8 +637,12 @@ struct GP_EditableStrokes_Iter {
} \
(void)0
+#define GPENCIL_ANY_SCULPT_MASK(flag) \
+ ((flag & (GP_SCULPT_MASK_SELECTMODE_POINT | GP_SCULPT_MASK_SELECTMODE_STROKE | \
+ GP_SCULPT_MASK_SELECTMODE_SEGMENT)))
+
/**
- * Iterate over all editable strokes using derived data in the current context,
+ * Iterate over all editable strokes using evaluated data in the current context,
* stopping on each usable layer + stroke pair (i.e. gpl and gps)
* to perform some operations on the stroke.
*
@@ -647,15 +651,15 @@ struct GP_EditableStrokes_Iter {
* \param gps: The identifier to use for current stroke being processed.
* Choose a suitable value to avoid name clashes.
*/
-#define GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) \
+#define GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps) \
{ \
struct GP_EditableStrokes_Iter gpstroke_iter = {{{0}}}; \
- Depsgraph *depsgraph_ = CTX_data_depsgraph_pointer(C); \
+ Depsgraph *depsgraph_ = CTX_data_ensure_evaluated_depsgraph(C); \
Object *obact_ = CTX_data_active_object(C); \
Object *obeval_ = DEG_get_evaluated_object(depsgraph_, obact_); \
bGPdata *gpd_ = CTX_data_gpencil_data(C); \
const bool is_multiedit_ = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd_); \
- int derived_idx = 0; \
+ int idx_eval = 0; \
for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { \
if (gpencil_layer_is_editable(gpl)) { \
bGPDframe *init_gpf_ = gpl->actframe; \
@@ -665,10 +669,11 @@ struct GP_EditableStrokes_Iter {
for (bGPDframe *gpf_ = init_gpf_; gpf_; gpf_ = gpf_->next) { \
if ((gpf_ == gpl->actframe) || ((gpf_->flag & GP_FRAME_SELECT) && is_multiedit_)) { \
ED_gpencil_parent_location(depsgraph_, obact_, gpd_, gpl, gpstroke_iter.diff_mat); \
- /* get derived frame with modifiers applied */ \
- bGPDframe *derived_gpf_ = &obeval_->runtime.derived_frames[derived_idx]; \
+ invert_m4_m4(gpstroke_iter.inverse_diff_mat, gpstroke_iter.diff_mat); \
+ /* get evaluated frame with modifiers applied */ \
+ bGPDframe *gpf_eval_ = &obeval_->runtime.gpencil_evaluated_frames[idx_eval]; \
/* loop over strokes */ \
- for (bGPDstroke *gps = derived_gpf_->strokes.first; gps; gps = gps->next) { \
+ for (bGPDstroke *gps = gpf_eval_->strokes.first; gps; gps = gps->next) { \
/* skip strokes that are invalid for current view */ \
if (ED_gpencil_stroke_can_use(C, gps) == false) \
continue; \
@@ -677,7 +682,7 @@ struct GP_EditableStrokes_Iter {
continue; \
/* ... Do Stuff With Strokes ... */
-#define GP_DERIVED_STROKES_END(gpstroke_iter) \
+#define GP_EVALUATED_STROKES_END(gpstroke_iter) \
} \
} \
if (!is_multiedit_) { \
@@ -685,7 +690,7 @@ struct GP_EditableStrokes_Iter {
} \
} \
} \
- derived_idx++; \
+ idx_eval++; \
} \
} \
(void)0
diff --git a/source/blender/editors/gpencil/gpencil_merge.c b/source/blender/editors/gpencil/gpencil_merge.c
index cb11bb4cd63..930911ffac5 100644
--- a/source/blender/editors/gpencil/gpencil_merge.c
+++ b/source/blender/editors/gpencil/gpencil_merge.c
@@ -449,7 +449,7 @@ static bool gp_strokes_merge_poll(bContext *C)
/* check material */
Material *ma = NULL;
- ma = give_current_material(ob, ob->actcol);
+ ma = BKE_material_gpencil_get(ob, ob->actcol);
if ((ma == NULL) || (ma->gp_style == NULL)) {
return false;
}
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index a5425d64c2e..3217c94eebd 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -423,7 +423,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const float mval[2], float out[
/* add small offset to keep stroke over the surface */
if ((depth) && (gpd->zdepth_offset > 0.0f) && (*p->align_flag & GP_PROJECT_DEPTH_VIEW)) {
- *depth *= (1.0f - gpd->zdepth_offset);
+ *depth *= (1.0f - (gpd->zdepth_offset / 1000.0f));
}
int mval_i[2];
@@ -563,7 +563,7 @@ static void gp_brush_angle(bGPdata *gpd, Brush *brush, tGPspoint *pt, const floa
static void gp_smooth_buffer(tGPsdata *p, float inf, int idx)
{
bGPdata *gpd = p->gpd;
- short num_points = gpd->runtime.sbuffer_used;
+ const short num_points = gpd->runtime.sbuffer_used;
/* Do nothing if not enough points to smooth out */
if ((num_points < 3) || (idx < 3) || (inf == 0.0f)) {
@@ -571,10 +571,7 @@ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx)
}
tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer;
- float steps = 4.0f;
- if (idx < 4) {
- steps--;
- }
+ const float steps = (idx < 4) ? 3.0f : 4.0f;
tGPspoint *pta = idx >= 4 ? &points[idx - 4] : NULL;
tGPspoint *ptb = idx >= 3 ? &points[idx - 3] : NULL;
@@ -583,29 +580,36 @@ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx)
float sco[2] = {0.0f};
float a[2], b[2], c[2], d[2];
+ float pressure = 0.0f;
const float average_fac = 1.0f / steps;
/* Compute smoothed coordinate by taking the ones nearby */
if (pta) {
copy_v2_v2(a, &pta->x);
madd_v2_v2fl(sco, a, average_fac);
+ pressure += pta->pressure * average_fac;
}
if (ptb) {
copy_v2_v2(b, &ptb->x);
madd_v2_v2fl(sco, b, average_fac);
+ pressure += ptb->pressure * average_fac;
}
if (ptc) {
copy_v2_v2(c, &ptc->x);
madd_v2_v2fl(sco, c, average_fac);
+ pressure += ptc->pressure * average_fac;
}
if (ptd) {
copy_v2_v2(d, &ptd->x);
madd_v2_v2fl(sco, d, average_fac);
+ pressure += ptd->pressure * average_fac;
}
- /* Based on influence factor, blend between original and optimal smoothed coordinate */
+ /* Based on influence factor, blend between original and optimal smoothed coordinate. */
interp_v2_v2v2(c, c, sco, inf);
copy_v2_v2(&ptc->x, c);
+ /* Interpolate pressure. */
+ ptc->pressure = interpf(ptc->pressure, pressure, inf);
}
/* add current stroke-point to buffer (returns whether point was successfully added) */
@@ -1240,6 +1244,14 @@ static void gp_stroke_newfrombuffer(tGPsdata *p)
/* Save material index */
gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(p->ob, p->brush);
+ if (gps->mat_nr < 0) {
+ if (p->ob->actcol - 1 < 0) {
+ gps->mat_nr = 0;
+ }
+ else {
+ gps->mat_nr = p->ob->actcol - 1;
+ }
+ }
/* calculate UVs along the stroke */
ED_gpencil_calc_stroke_uv(obact, gps);
@@ -2128,15 +2140,6 @@ static void gp_paint_initstroke(tGPsdata *p, eGPencil_PaintModes paintmode, Deps
/* Ensure this gets set... */
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_SCULPT_SETT_FLAG_SELECT_MASK) {
- p->flags |= GP_PAINTFLAG_SELECTMASK;
- }
- }
-
if (has_layer_to_erase == false) {
p->status = GP_STATUS_ERROR;
return;
diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c
index 25913fe821a..8d4c75d2e8c 100644
--- a/source/blender/editors/gpencil/gpencil_primitive.c
+++ b/source/blender/editors/gpencil/gpencil_primitive.c
@@ -330,7 +330,15 @@ static void gp_primitive_set_initdata(bContext *C, tGPDprimitive *tgpi)
gps->flag |= GP_STROKE_3DSPACE;
- gps->mat_nr = BKE_gpencil_object_material_get_index(tgpi->ob, tgpi->mat);
+ gps->mat_nr = BKE_gpencil_object_material_get_index_from_brush(tgpi->ob, tgpi->brush);
+ if (gps->mat_nr < 0) {
+ if (tgpi->ob->actcol - 1 < 0) {
+ gps->mat_nr = 0;
+ }
+ else {
+ gps->mat_nr = tgpi->ob->actcol - 1;
+ }
+ }
/* allocate memory for storage points, but keep empty */
gps->totpoints = 0;
@@ -959,7 +967,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi)
/* add small offset to keep stroke over the surface */
if ((depth_arr) && (gpd->zdepth_offset > 0.0f)) {
- depth_arr[i] *= (1.0f - gpd->zdepth_offset);
+ depth_arr[i] *= (1.0f - (gpd->zdepth_offset / 1000.0f));
}
/* convert screen-coordinates to 3D coordinates */
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 01a2ac757d6..f4484624d5a 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -67,13 +67,30 @@
/** \name Shared Utilities
* \{ */
+/* Convert sculpt mask mode to Select mode */
+static int gpencil_select_mode_from_sculpt(eGP_Sculpt_SelectMaskFlag mode)
+{
+ if (mode & GP_SCULPT_MASK_SELECTMODE_POINT) {
+ return GP_SELECTMODE_POINT;
+ }
+ else if (mode & GP_SCULPT_MASK_SELECTMODE_STROKE) {
+ return GP_SELECTMODE_STROKE;
+ }
+ else if (mode & GP_SCULPT_MASK_SELECTMODE_SEGMENT) {
+ return GP_SELECTMODE_SEGMENT;
+ }
+ else {
+ return GP_SELECTMODE_POINT;
+ }
+}
+
static bool gpencil_select_poll(bContext *C)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
if (GPENCIL_SCULPT_MODE(gpd)) {
ToolSettings *ts = CTX_data_tool_settings(C);
- if ((ts->gp_sculpt.flag & GP_SCULPT_SETT_FLAG_SELECT_MASK) == 0) {
+ if (!(GPENCIL_ANY_SCULPT_MASK(ts->gpencil_selectmode_sculpt))) {
return false;
}
}
@@ -94,6 +111,19 @@ static bool gpencil_select_poll(bContext *C)
/* -------------------------------------------------------------------- */
/** \name Select All Operator
* \{ */
+static bool gpencil_select_all_poll(bContext *C)
+{
+ bGPdata *gpd = ED_gpencil_data_get_active(C);
+
+ /* we just need some visible strokes, and to be in editmode or other modes only to catch event */
+ if (GPENCIL_ANY_MODE(gpd)) {
+ if (gpd->layers.first) {
+ return true;
+ }
+ }
+
+ return false;
+}
static int gpencil_select_all_exec(bContext *C, wmOperator *op)
{
@@ -110,6 +140,14 @@ static int gpencil_select_all_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
+ /* For sculpt mode, if mask is disable, only allows deselect */
+ if (GPENCIL_SCULPT_MODE(gpd)) {
+ ToolSettings *ts = CTX_data_tool_settings(C);
+ if ((!(GPENCIL_ANY_SCULPT_MASK(ts->gpencil_selectmode_sculpt))) && (action != SEL_DESELECT)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+
ED_gpencil_select_toggle_all(C, action);
/* updates */
@@ -132,7 +170,7 @@ void GPENCIL_OT_select_all(wmOperatorType *ot)
/* callbacks */
ot->exec = gpencil_select_all_exec;
- ot->poll = gpencil_select_poll;
+ ot->poll = gpencil_select_all_poll;
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
@@ -928,7 +966,11 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
{
bGPdata *gpd = ED_gpencil_data_get_active(C);
ToolSettings *ts = CTX_data_tool_settings(C);
- const int selectmode = ts->gpencil_selectmode;
+ Object *ob = CTX_data_active_object(C);
+
+ const int selectmode = (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) ?
+ gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) :
+ ts->gpencil_selectmode_edit;
const float scale = ts->gp_sculpt.isect_threshold;
/* if not edit/sculpt mode, the event is catched but not processed */
@@ -972,12 +1014,12 @@ static int gpencil_circle_select_exec(bContext *C, wmOperator *op)
rect.ymax = my + radius;
/* find visible strokes, and select if hit */
- GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
+ GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
{
changed |= gp_stroke_do_circle_sel(
gpl, gps, &gsc, mx, my, radius, select, &rect, gpstroke_iter.diff_mat, selectmode, scale);
}
- GP_DERIVED_STROKES_END(gpstroke_iter);
+ GP_EVALUATED_STROKES_END(gpstroke_iter);
/* updates */
if (changed) {
@@ -1035,12 +1077,18 @@ static int gpencil_generic_select_exec(bContext *C,
GPencilTestFn is_inside_fn,
void *user_data)
{
+ Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
ToolSettings *ts = CTX_data_tool_settings(C);
ScrArea *sa = CTX_wm_area(C);
- const bool strokemode = ((ts->gpencil_selectmode == GP_SELECTMODE_STROKE) &&
+
+ const short selectmode = (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) ?
+ gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) :
+ ts->gpencil_selectmode_edit;
+
+ const bool strokemode = ((selectmode == GP_SELECTMODE_STROKE) &&
((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
- const bool segmentmode = ((ts->gpencil_selectmode == GP_SELECTMODE_SEGMENT) &&
+ const bool segmentmode = ((selectmode == GP_SELECTMODE_SEGMENT) &&
((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
const float scale = ts->gp_sculpt.isect_threshold;
@@ -1075,7 +1123,7 @@ static int gpencil_generic_select_exec(bContext *C,
}
/* select/deselect points */
- GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
+ GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
{
bGPDspoint *pt;
@@ -1088,7 +1136,6 @@ static int gpencil_generic_select_exec(bContext *C,
/* convert point coords to screenspace */
const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
-
if (strokemode == false) {
const bool is_select = (pt->runtime.pt_orig->flag & GP_SPOINT_SELECT) != 0;
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
@@ -1143,7 +1190,7 @@ static int gpencil_generic_select_exec(bContext *C,
/* Ensure that stroke selection is in sync with its points */
BKE_gpencil_stroke_sync_selection(gps->runtime.gps_orig);
}
- GP_DERIVED_STROKES_END(gpstroke_iter);
+ GP_EVALUATED_STROKES_END(gpstroke_iter);
/* if paint mode,delete selected points */
if (gpd->flag & GP_DATA_STROKE_PAINTMODE) {
@@ -1318,6 +1365,7 @@ static void deselect_all_selected(bContext *C)
static int gpencil_select_exec(bContext *C, wmOperator *op)
{
ScrArea *sa = CTX_wm_area(C);
+ Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
ToolSettings *ts = CTX_data_tool_settings(C);
const float scale = ts->gp_sculpt.isect_threshold;
@@ -1348,8 +1396,12 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
}
/* if select mode is stroke, use whole stroke */
- if (ts->gpencil_selectmode == GP_SELECTMODE_STROKE) {
- whole = true;
+ if ((ob) && (ob->mode == OB_MODE_SCULPT_GPENCIL)) {
+ whole = (bool)(gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) ==
+ GP_SELECTMODE_STROKE);
+ }
+ else {
+ whole = (bool)(ts->gpencil_selectmode_edit == GP_SELECTMODE_STROKE);
}
/* init space conversion stuff */
@@ -1360,7 +1412,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
/* First Pass: Find stroke point which gets hit */
/* XXX: maybe we should go from the top of the stack down instead... */
- GP_DERIVED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
+ GP_EVALUATED_STROKES_BEGIN(gpstroke_iter, C, gpl, gps)
{
bGPDspoint *pt;
int i;
@@ -1393,7 +1445,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
}
}
}
- GP_DERIVED_STROKES_END(gpstroke_iter);
+ GP_EVALUATED_STROKES_END(gpstroke_iter);
/* Abort if nothing hit... */
if (ELEM(NULL, hit_stroke, hit_point)) {
@@ -1454,7 +1506,11 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
hit_stroke->flag |= GP_STROKE_SELECT;
/* expand selection to segment */
- if (ts->gpencil_selectmode == GP_SELECTMODE_SEGMENT) {
+ const short selectmode = (ob && ob->mode == OB_MODE_SCULPT_GPENCIL) ?
+ gpencil_select_mode_from_sculpt(ts->gpencil_selectmode_sculpt) :
+ ts->gpencil_selectmode_edit;
+
+ if (selectmode == GP_SELECTMODE_SEGMENT) {
float r_hita[3], r_hitb[3];
bool hit_select = (bool)(hit_point->flag & GP_SPOINT_SELECT);
ED_gpencil_select_stroke_segment(
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 2a0f16a4bbf..d7492b5be4d 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -401,17 +401,7 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C,
/* Create new layer */
/* TODO: have some way of specifying that we don't want this? */
- {
- /* "New Layer" entry */
- item_tmp.identifier = "__CREATE__";
- item_tmp.name = "New Layer";
- item_tmp.value = -1;
- item_tmp.icon = ICON_ADD;
- RNA_enum_item_add(&item, &totitem, &item_tmp);
- /* separator */
- RNA_enum_item_add_separator(&item, &totitem);
- }
const int tot = BLI_listbase_count(&gpd->layers);
/* Existing layers */
for (gpl = gpd->layers.last, i = 0; gpl; gpl = gpl->prev, i++) {
@@ -428,6 +418,17 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C,
RNA_enum_item_add(&item, &totitem, &item_tmp);
}
+ {
+ /* separator */
+ RNA_enum_item_add_separator(&item, &totitem);
+
+ /* "New Layer" entry */
+ item_tmp.identifier = "__CREATE__";
+ item_tmp.name = "New Layer";
+ item_tmp.value = -1;
+ item_tmp.icon = ICON_ADD;
+ RNA_enum_item_add(&item, &totitem, &item_tmp);
+ }
RNA_enum_item_end(&item, &totitem);
*r_free = true;
@@ -2063,7 +2064,7 @@ void ED_gpencil_update_color_uv(Main *bmain, Material *mat)
if (ED_gpencil_stroke_color_use(ob, gpl, gps) == false) {
continue;
}
- gps_ma = give_current_material(ob, gps->mat_nr + 1);
+ gps_ma = BKE_material_gpencil_get(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/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h
index 101a65d151a..a49f02d28fe 100644
--- a/source/blender/editors/include/BIF_glutil.h
+++ b/source/blender/editors/include/BIF_glutil.h
@@ -24,7 +24,6 @@
#ifndef __BIF_GLUTIL_H__
#define __BIF_GLUTIL_H__
-struct rctf;
struct rcti;
struct ColorManagedDisplaySettings;
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 6629eed8328..48d0a5fe8be 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -42,7 +42,6 @@ struct ReportList;
struct Scene;
struct UndoType;
struct View3D;
-struct ViewContext;
struct ViewLayer;
struct bArmature;
struct bContext;
@@ -75,12 +74,14 @@ typedef struct EditBone {
int flag;
int layer;
+ /* Envelope distance & weight */
float dist, weight;
/** put them in order! transform uses this as scale */
float xwidth, length, zwidth;
float rad_head, rad_tail;
/* Bendy-Bone parameters */
+ short segments;
float roll1, roll2;
float curve_in_x, curve_in_y;
float curve_out_x, curve_out_y;
@@ -91,8 +92,6 @@ typedef struct EditBone {
/** for envelope scaling */
float oldlength;
- short segments;
-
/** Type of next/prev bone handles */
char bbone_prev_type;
char bbone_next_type;
@@ -229,15 +228,9 @@ void ED_armature_edit_transform_mirror_update(struct Object *obedit);
void ED_armature_origin_set(
struct Main *bmain, struct Object *ob, const float cursor[3], int centermode, int around);
-void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4], const bool do_props);
-void ED_armature_transform_apply(struct Main *bmain,
- struct Object *ob,
- float mat[4][4],
- const bool do_props);
-void ED_armature_transform(struct Main *bmain,
- struct bArmature *arm,
- float mat[4][4],
- const bool do_props);
+void ED_armature_edit_transform(struct bArmature *arm, const float mat[4][4], const bool do_props);
+
+void ED_armature_transform(struct bArmature *arm, const float mat[4][4], const bool do_props);
#define ARM_GROUPS_NAME 1
#define ARM_GROUPS_ENVELOPE 2
diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h
index 7cee5a358f4..22bf22e04d3 100644
--- a/source/blender/editors/include/ED_clip.h
+++ b/source/blender/editors/include/ED_clip.h
@@ -29,7 +29,6 @@ struct ImBuf;
struct Main;
struct Mask;
struct MovieClip;
-struct Scene;
struct SpaceClip;
struct bContext;
struct bScreen;
diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h
index 7273f857a41..dc42237d804 100644
--- a/source/blender/editors/include/ED_fileselect.h
+++ b/source/blender/editors/include/ED_fileselect.h
@@ -34,17 +34,32 @@ struct wmWindowManager;
#define FILE_LAYOUT_HOR 1
#define FILE_LAYOUT_VER 2
-#define MAX_FILE_COLUMN 4
-
-typedef enum FileListColumns {
+typedef enum FileAttributeColumnType {
+ COLUMN_NONE = -1,
COLUMN_NAME = 0,
- COLUMN_DATE,
- COLUMN_TIME,
+ COLUMN_DATETIME,
COLUMN_SIZE,
-} FileListColumns;
+
+ ATTRIBUTE_COLUMN_MAX
+} FileAttributeColumnType;
+
+typedef struct FileAttributeColumn {
+ /** UI name for this column */
+ const char *name;
+
+ float width;
+ /* The sort type to use when sorting by this column. */
+ int sort_type; /* eFileSortType */
+
+ /* Alignment of column texts, header text is always left aligned */
+ int text_align; /* eFontStyle_Align */
+} FileAttributeColumn;
typedef struct FileLayout {
/* view settings - XXX - move into own struct */
+ int offset_top;
+ /* Height of the header for the different FileAttributeColumn's. */
+ int attribute_column_header_h;
int prv_w;
int prv_h;
int tile_w;
@@ -54,13 +69,17 @@ typedef struct FileLayout {
int prv_border_x;
int prv_border_y;
int rows;
- int columns;
+ /* Those are the major layout columns the files are distributed across, not to be confused with
+ * 'attribute_columns' array below. */
+ int flow_columns;
int width;
int height;
int flag;
int dirty;
int textheight;
- float column_widths[MAX_FILE_COLUMN];
+ /* The columns for each item (name, modification date/time, size). Not to be confused with the
+ * 'flow_columns' above. */
+ FileAttributeColumn attribute_columns[ATTRIBUTE_COLUMN_MAX];
/* When we change display size, we may have to update static strings like size of files... */
short curr_size;
@@ -72,6 +91,7 @@ typedef struct FileSelection {
} FileSelection;
struct rcti;
+struct View2D;
struct FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile);
@@ -87,6 +107,17 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, struct ARegion *ar);
int ED_fileselect_layout_offset(FileLayout *layout, int x, int y);
FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const struct rcti *rect);
+void ED_fileselect_layout_maskrect(const FileLayout *layout,
+ const struct View2D *v2d,
+ struct rcti *r_rect);
+bool ED_fileselect_layout_is_inside_pt(const FileLayout *layout,
+ const struct View2D *v2d,
+ int x,
+ int y);
+bool ED_fileselect_layout_isect_rect(const FileLayout *layout,
+ const struct View2D *v2d,
+ const struct rcti *rect,
+ struct rcti *r_dst);
void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y);
void ED_operatormacros_file(void);
diff --git a/source/blender/editors/include/ED_gizmo_library.h b/source/blender/editors/include/ED_gizmo_library.h
index f14648bc026..a3e2e643509 100644
--- a/source/blender/editors/include/ED_gizmo_library.h
+++ b/source/blender/editors/include/ED_gizmo_library.h
@@ -43,10 +43,8 @@ void ED_gizmotypes_value_2d(void);
void ED_gizmogrouptypes_value_2d(void);
struct Object;
-struct Scene;
struct bContext;
struct wmGizmo;
-struct wmGizmoGroup;
/* -------------------------------------------------------------------- */
/* Shape Presets
diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h
index 6410e6630a7..470eb58c72b 100644
--- a/source/blender/editors/include/ED_gpencil.h
+++ b/source/blender/editors/include/ED_gpencil.h
@@ -27,7 +27,6 @@
struct ID;
struct ListBase;
struct PointerRNA;
-struct rcti;
struct Brush;
struct bGPDframe;
@@ -39,13 +38,11 @@ struct tGPspoint;
struct ARegion;
struct Depsgraph;
-struct EvaluationContext;
struct Main;
struct RegionView3D;
struct ReportList;
struct Scene;
struct ScrArea;
-struct ToolSettings;
struct View3D;
struct ViewLayer;
struct bContext;
@@ -58,8 +55,6 @@ struct bAnimContext;
struct wmKeyConfig;
struct wmOperator;
-struct wmWindow;
-struct wmWindowManager;
/* ------------- Grease-Pencil Runtime Data ---------------- */
diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h
index a09e1d579fd..7d69f86dbf8 100644
--- a/source/blender/editors/include/ED_image.h
+++ b/source/blender/editors/include/ED_image.h
@@ -31,7 +31,6 @@ struct ImageUser;
struct ReportList;
struct Scene;
struct SpaceImage;
-struct ToolSettings;
struct ViewLayer;
struct bContext;
struct wmWindowManager;
diff --git a/source/blender/editors/include/ED_keyframes_draw.h b/source/blender/editors/include/ED_keyframes_draw.h
index 05f641abe91..2630feaa9d3 100644
--- a/source/blender/editors/include/ED_keyframes_draw.h
+++ b/source/blender/editors/include/ED_keyframes_draw.h
@@ -31,7 +31,6 @@ struct FCurve;
struct ListBase;
struct MaskLayer;
struct Object;
-struct Palette;
struct Scene;
struct View2D;
struct bAction;
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index bbeeeade822..42e5add2ef0 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -44,8 +44,6 @@ struct bPoseChannel;
struct ReportList;
struct bContext;
-struct Depsgraph;
-
struct EnumPropertyItem;
struct PointerRNA;
struct PropertyRNA;
diff --git a/source/blender/editors/include/ED_markers.h b/source/blender/editors/include/ED_markers.h
index a883187327f..a9e57ecc13d 100644
--- a/source/blender/editors/include/ED_markers.h
+++ b/source/blender/editors/include/ED_markers.h
@@ -29,7 +29,6 @@ struct TimeMarker;
struct bAnimContext;
struct bContext;
struct wmKeyConfig;
-struct wmKeyMap;
/* Drawing API ------------------------------ */
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 5ebba4e5d25..ee4798430ef 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -45,7 +45,6 @@ struct Mesh;
struct Object;
struct ReportList;
struct Scene;
-struct ToolSettings;
struct UndoType;
struct UvMapVert;
struct UvMapVert;
@@ -55,7 +54,6 @@ struct View3D;
struct ViewContext;
struct bContext;
struct bDeformGroup;
-struct rcti;
struct wmKeyConfig;
struct wmOperator;
@@ -105,7 +103,9 @@ bool EDBM_vert_color_check(struct BMEditMesh *em);
bool EDBM_mesh_hide(struct BMEditMesh *em, bool swap);
bool EDBM_mesh_reveal(struct BMEditMesh *em, bool select);
-void EDBM_update_generic(struct BMEditMesh *em, const bool do_tessface, const bool is_destructive);
+void EDBM_update_generic(struct BMEditMesh *em,
+ const bool do_tessellation,
+ const bool is_destructive);
struct UvElementMap *BM_uv_element_map_create(struct BMesh *bm,
const bool selected,
@@ -138,13 +138,21 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree,
struct View3D *v3d,
struct Object *obedit);
+/* editmesh_automerge.c */
+void EDBM_automerge(struct Object *ob, bool update, const char hflag, const float dist);
+void EDBM_automerge_and_split(struct Object *ob,
+ bool split_edges,
+ bool split_faces,
+ bool update,
+ const char hflag,
+ const float dist);
+
/* editmesh_undo.c */
void ED_mesh_undosys_type(struct UndoType *ut);
/* editmesh_select.c */
void EDBM_select_mirrored(
struct BMEditMesh *em, const int axis, const bool extend, int *r_totmirr, int *r_totfail);
-void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update, const char hflag);
struct BMVert *EDBM_vert_find_nearest_ex(struct ViewContext *vc,
float *r_dist,
@@ -188,8 +196,11 @@ bool EDBM_unified_findnearest(struct ViewContext *vc,
bool EDBM_unified_findnearest_from_raycast(struct ViewContext *vc,
struct Base **bases,
const uint bases_len,
- bool use_boundary,
- int *r_base_index,
+ bool use_boundary_vertices,
+ bool use_boundary_edges,
+ int *r_base_index_vert,
+ int *r_base_index_edge,
+ int *r_base_index_face,
struct BMVert **r_eve,
struct BMEdge **r_eed,
struct BMFace **r_efa);
@@ -239,15 +250,30 @@ void EDBM_preselect_edgering_update_from_edge(struct EditMesh_PreSelEdgeRing *ps
/* editmesh_preselect_elem.c */
struct EditMesh_PreSelElem;
+typedef enum eEditMesh_PreSelPreviewAction {
+ PRESELECT_ACTION_TRANSFORM = 1,
+ PRESELECT_ACTION_CREATE = 2,
+ PRESELECT_ACTION_DELETE = 3,
+} eEditMesh_PreSelPreviewAction;
+
struct EditMesh_PreSelElem *EDBM_preselect_elem_create(void);
void EDBM_preselect_elem_destroy(struct EditMesh_PreSelElem *psel);
void EDBM_preselect_elem_clear(struct EditMesh_PreSelElem *psel);
+void EDBM_preselect_preview_clear(struct EditMesh_PreSelElem *psel);
void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matrix[4][4]);
void EDBM_preselect_elem_update_from_single(struct EditMesh_PreSelElem *psel,
struct BMesh *bm,
struct BMElem *ele,
const float (*coords)[3]);
+void EDBM_preselect_elem_update_preview(struct EditMesh_PreSelElem *psel,
+ struct ViewContext *vc,
+ struct BMesh *bm,
+ struct BMElem *ele,
+ const int mval[2]);
+void EDBM_preselect_action_set(struct EditMesh_PreSelElem *psel,
+ eEditMesh_PreSelPreviewAction action);
+eEditMesh_PreSelPreviewAction EDBM_preselect_action_get(struct EditMesh_PreSelElem *psel);
/* mesh_ops.c */
void ED_operatortypes_mesh(void);
void ED_operatormacros_mesh(void);
@@ -358,21 +384,14 @@ void ED_mesh_geometry_add(
struct Mesh *mesh, struct ReportList *reports, int verts, int edges, int faces);
#endif
void ED_mesh_polys_add(struct Mesh *mesh, struct ReportList *reports, int count);
-void ED_mesh_tessfaces_add(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_edges_add(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_loops_add(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_vertices_add(struct Mesh *mesh, struct ReportList *reports, int count);
-void ED_mesh_faces_remove(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_edges_remove(struct Mesh *mesh, struct ReportList *reports, int count);
void ED_mesh_vertices_remove(struct Mesh *mesh, struct ReportList *reports, int count);
-void ED_mesh_calc_tessface(struct Mesh *mesh, bool free_mpoly);
-void ED_mesh_update(struct Mesh *mesh,
- struct bContext *C,
- bool calc_edges,
- bool calc_edges_loose,
- bool calc_tessface);
+void ED_mesh_update(struct Mesh *mesh, struct bContext *C, bool calc_edges, bool calc_edges_loose);
void ED_mesh_uv_texture_ensure(struct Mesh *me, const char *name);
int ED_mesh_uv_texture_add(struct Mesh *me,
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 7b9a96e4d07..c481c19a552 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -34,7 +34,6 @@ struct EnumPropertyItem;
struct EnumPropertyItem;
struct ID;
struct Main;
-struct Menu;
struct ModifierData;
struct Object;
struct PointerRNA;
@@ -44,16 +43,15 @@ struct Scene;
struct ShaderFxData;
struct View3D;
struct ViewLayer;
+struct XFormObjectData;
struct bConstraint;
struct bContext;
struct bFaceMap;
struct bPoseChannel;
struct uiLayout;
struct wmKeyConfig;
-struct wmKeyMap;
struct wmOperator;
struct wmOperatorType;
-struct wmWindow;
struct wmWindowManager;
#include "DNA_object_enums.h"
@@ -403,6 +401,12 @@ bool ED_object_jump_to_bone(struct bContext *C,
void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum);
void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum);
+/* object_data_transform.c */
+struct XFormObjectData *ED_object_data_xform_create(struct ID *id);
+void ED_object_data_xform_destroy(struct XFormObjectData *xod);
+
+void ED_object_data_xform_by_mat4(struct XFormObjectData *xod, const float mat[4][4]);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h
index e94aedc2b2b..3015d8d9cdc 100644
--- a/source/blender/editors/include/ED_outliner.h
+++ b/source/blender/editors/include/ED_outliner.h
@@ -30,4 +30,18 @@ bool ED_outliner_collections_editor_poll(struct bContext *C);
void ED_outliner_selected_objects_get(const struct bContext *C, struct ListBase *objects);
+Base *ED_outliner_give_base_under_cursor(struct bContext *C, const int mval[2]);
+
+void ED_outliner_select_sync_from_object_tag(struct bContext *C);
+void ED_outliner_select_sync_from_edit_bone_tag(struct bContext *C);
+void ED_outliner_select_sync_from_pose_bone_tag(struct bContext *C);
+void ED_outliner_select_sync_from_sequence_tag(struct bContext *C);
+void ED_outliner_select_sync_from_all_tag(struct bContext *C);
+
+bool ED_outliner_select_sync_is_dirty(const struct bContext *C);
+
+void ED_outliner_select_sync_from_outliner(struct bContext *C, struct SpaceOutliner *soops);
+
+void ED_outliner_select_sync_flag_outliners(const struct bContext *C);
+
#endif /* __ED_OUTLINER_H__ */
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index c7ee7be49b5..d0fab134dcc 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -39,10 +39,8 @@ struct Depsgraph;
struct IDProperty;
struct Main;
struct MenuType;
-struct PropertyRNA;
struct Scene;
struct SpaceLink;
-struct ViewLayer;
struct WorkSpace;
struct WorkSpaceInstanceHook;
struct bContext;
@@ -50,7 +48,6 @@ struct bScreen;
struct rcti;
struct uiBlock;
struct uiLayout;
-struct wmEvent;
struct wmKeyConfig;
struct wmMsgBus;
struct wmMsgSubscribeKey;
diff --git a/source/blender/editors/include/ED_sculpt.h b/source/blender/editors/include/ED_sculpt.h
index 034e002f86a..d907ba4e581 100644
--- a/source/blender/editors/include/ED_sculpt.h
+++ b/source/blender/editors/include/ED_sculpt.h
@@ -25,10 +25,7 @@
#define __ED_SCULPT_H__
struct ARegion;
-struct ListBase;
struct Object;
-struct RegionView3D;
-struct UndoStep;
struct UndoType;
struct ViewContext;
struct bContext;
diff --git a/source/blender/editors/include/ED_time_scrub_ui.h b/source/blender/editors/include/ED_time_scrub_ui.h
index b43e674224c..f010c45d939 100644
--- a/source/blender/editors/include/ED_time_scrub_ui.h
+++ b/source/blender/editors/include/ED_time_scrub_ui.h
@@ -24,7 +24,6 @@
#ifndef __ED_TIME_SCRUB_UI_H__
#define __ED_TIME_SCRUB_UI_H__
-struct View2DGrid;
struct bContext;
struct bDopeSheet;
struct wmEvent;
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 3605a245187..d8b65aa5975 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -26,18 +26,11 @@
/* ******************* Registration Function ********************** */
-struct ARegion;
-struct ListBase;
-struct Main;
struct Object;
struct SnapObjectContext;
struct SnapObjectParams;
-struct View3D;
-struct WorkSpace;
struct bContext;
-struct wmEvent;
struct wmKeyConfig;
-struct wmKeyMap;
struct wmOperatorType;
void ED_keymap_transform(struct wmKeyConfig *keyconf);
@@ -97,6 +90,10 @@ enum TfmMode {
#define CTX_PAINT_CURVE (1 << 8)
#define CTX_GPENCIL_STROKES (1 << 9)
#define CTX_CURSOR (1 << 10)
+/** When transforming object's, adjust the object data so it stays in the same place. */
+#define CTX_OBMODE_XFORM_OBDATA (1 << 11)
+/** Transform object parents without moving their children. */
+#define CTX_OBMODE_XFORM_SKIP_CHILDREN (1 << 12)
/* Standalone call to get the transformation center corresponding to the current situation
* returns 1 if successful, 0 otherwise (usually means there's no selection)
@@ -112,7 +109,6 @@ struct Scene;
struct TransInfo;
struct wmGizmoGroup;
struct wmGizmoGroupType;
-struct wmOperator;
/* UNUSED */
// int BIF_snappingSupported(struct Object *obedit);
@@ -197,12 +193,12 @@ bool peelObjectsSnapContext(struct SnapObjectContext *sctx,
float r_no[3],
float *r_thickness);
-bool snapObjectsTransform(struct TransInfo *t,
- const float mval[2],
- float *dist_px,
- /* return args */
- float r_loc[3],
- float r_no[3]);
+short snapObjectsTransform(struct TransInfo *t,
+ const float mval[2],
+ float *dist_px,
+ /* return args */
+ float r_loc[3],
+ float r_no[3]);
bool snapNodesTransform(struct TransInfo *t,
const int mval[2],
/* return args */
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index f27523bb1f8..40e0005b487 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -32,8 +32,6 @@ struct Main;
struct Object;
struct Scene;
struct View3D;
-struct ViewLayer;
-struct bContext;
/* transform_snap_object.c */
@@ -125,6 +123,7 @@ short ED_transform_snap_object_project_view3d_ex(struct SnapObjectContext *sctx,
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2],
+ const float prev_co[3],
float *dist_px,
float r_loc[3],
float r_no[3],
@@ -135,6 +134,7 @@ bool ED_transform_snap_object_project_view3d(struct SnapObjectContext *sctx,
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2],
+ const float prev_co[3],
float *dist_px,
/* return args */
float r_loc[3],
diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h
index 8dd2dab5209..1856ad8454b 100644
--- a/source/blender/editors/include/ED_uvedit.h
+++ b/source/blender/editors/include/ED_uvedit.h
@@ -37,7 +37,6 @@ struct Object;
struct Scene;
struct SpaceImage;
struct ToolSettings;
-struct View3D;
struct ViewLayer;
struct bNode;
struct wmKeyConfig;
diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h
index 67dfb184d19..139b306b533 100644
--- a/source/blender/editors/include/ED_view3d.h
+++ b/source/blender/editors/include/ED_view3d.h
@@ -38,8 +38,6 @@ struct Camera;
struct CustomData_MeshMasks;
struct Depsgraph;
struct EditBone;
-struct GPUFX;
-struct GPUFXSettings;
struct GPUOffScreen;
struct GPUViewport;
struct ID;
@@ -58,7 +56,6 @@ struct View3D;
struct View3DShading;
struct ViewContext;
struct ViewLayer;
-struct WorkSpace;
struct bContext;
struct bPoseChannel;
struct bScreen;
@@ -690,6 +687,10 @@ bool ED_view3d_distance_set_from_location(struct RegionView3D *rv3d,
float ED_scene_grid_scale(struct Scene *scene, const char **grid_unit);
float ED_view3d_grid_scale(struct Scene *scene, struct View3D *v3d, const char **grid_unit);
+void ED_view3d_grid_steps(struct Scene *scene,
+ struct View3D *v3d,
+ struct RegionView3D *rv3d,
+ float *r_grid_steps);
float ED_view3d_grid_view_scale(struct Scene *scene,
struct View3D *v3d,
struct RegionView3D *rv3d,
diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h
index 03a49943ed3..41ac1b6b452 100644
--- a/source/blender/editors/include/UI_icons.h
+++ b/source/blender/editors/include/UI_icons.h
@@ -483,7 +483,7 @@ DEF_ICON(UNDERLINE)
DEF_ICON(SMALL_CAPS)
DEF_ICON_BLANK(742)
DEF_ICON_BLANK(743)
-DEF_ICON_BLANK(744)
+DEF_ICON_MODIFIER(CON_ACTION)
DEF_ICON_BLANK(745)
DEF_ICON_BLANK(746)
DEF_ICON_BLANK(747)
@@ -667,8 +667,8 @@ DEF_ICON(PARTICLE_PATH)
/* EDITING */
DEF_ICON_BLANK(669)
DEF_ICON_BLANK(670)
-DEF_ICON_BLANK(671)
-DEF_ICON_BLANK(672)
+DEF_ICON(SNAP_PERPENDICULAR)
+DEF_ICON(SNAP_MIDPOINT)
DEF_ICON(SNAP_OFF)
DEF_ICON(SNAP_ON)
DEF_ICON(SNAP_NORMAL)
@@ -866,8 +866,8 @@ DEF_ICON(SEQ_LUMA_WAVEFORM)
DEF_ICON(SEQ_CHROMA_SCOPE)
DEF_ICON(SEQ_HISTOGRAM)
DEF_ICON(SEQ_SPLITVIEW)
-DEF_ICON_BLANK(870)
-DEF_ICON_BLANK(871)
+DEF_ICON(SEQ_STRIP_META)
+DEF_ICON(SEQ_STRIP_DUPLICATE)
DEF_ICON_BLANK(872)
DEF_ICON(IMAGE_RGB) // XXX CHANGE TO STRAIGHT ALPHA, Z ETC
DEF_ICON(IMAGE_RGB_ALPHA)
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 5ef3e5d8987..aa1044647c8 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -31,7 +31,6 @@
/* Struct Declarations */
struct ARegion;
-struct ARegionType;
struct AutoComplete;
struct ID;
struct IDProperty;
@@ -90,7 +89,7 @@ typedef struct uiPopupBlockHandle uiPopupBlockHandle;
* For #ARegion.overlap regions, pass events though if they don't overlap
* the regions contents (the usable part of the #View2D and buttons).
*
- * The margin is needed so it's not possible to accidentally click inbetween buttons.
+ * The margin is needed so it's not possible to accidentally click in between buttons.
*/
#define UI_REGION_OVERLAP_MARGIN (U.widget_unit / 3)
diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h
index 1db584f0f59..a73e2655b7d 100644
--- a/source/blender/editors/include/UI_resources.h
+++ b/source/blender/editors/include/UI_resources.h
@@ -255,6 +255,7 @@ typedef enum ThemeColorID {
TH_MATCH, /* highlight color for search matches */
TH_SELECT_HIGHLIGHT, /* highlight color for selected outliner item */
+ TH_SELECT_ACTIVE, /* highlight color for active outliner item */
TH_SELECTED_OBJECT, /* selected object color for outliner */
TH_ACTIVE_OBJECT, /* active object color for outliner */
TH_EDITED_OBJECT, /* edited object color for outliner */
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 7a123599be5..ee354df3a25 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -908,12 +908,12 @@ void UI_but_execute(const bContext *C, ARegion *ar, uiBut *but)
* returns false if undo needs to be disabled. */
static bool ui_but_is_rna_undo(const uiBut *but)
{
- if (but->rnapoin.id.data) {
+ if (but->rnapoin.owner_id) {
/* avoid undo push for buttons who's ID are screen or wm level
* we could disable undo for buttons with no ID too but may have
* unforeseen consequences, so best check for ID's we _know_ are not
* handled by undo - campbell */
- ID *id = but->rnapoin.id.data;
+ ID *id = but->rnapoin.owner_id;
if (ID_CHECK_UNDO(id) == false) {
return false;
}
@@ -1226,8 +1226,8 @@ static bool ui_but_event_property_operator_string(const bContext *C,
*/
char *data_path = NULL;
- if (ptr->id.data) {
- ID *id = ptr->id.data;
+ if (ptr->owner_id) {
+ ID *id = ptr->owner_id;
if (GS(id->name) == ID_SCR) {
/* screen/editor property
@@ -1731,7 +1731,7 @@ static void ui_block_message_subscribe(ARegion *ar, struct wmMsgBus *mbus, uiBlo
if ((but_prev && (but_prev->rnaprop == but->rnaprop) &&
(but_prev->rnapoin.type == but->rnapoin.type) &&
(but_prev->rnapoin.data == but->rnapoin.data) &&
- (but_prev->rnapoin.id.data == but->rnapoin.id.data)) == false) {
+ (but_prev->rnapoin.owner_id == but->rnapoin.owner_id)) == false) {
/* TODO: could make this into utility function. */
WM_msg_subscribe_rna(mbus,
&but->rnapoin,
@@ -2055,7 +2055,7 @@ bool ui_but_is_compatible(const uiBut *but_a, const uiBut *but_b)
}
if (but_a->rnaprop) {
- /* skip 'rnapoin.data', 'rnapoin.id.data'
+ /* skip 'rnapoin.data', 'rnapoin.owner_id'
* allow different data to have the same props edited at once */
if (but_a->rnapoin.type != but_b->rnapoin.type) {
return false;
@@ -2479,7 +2479,7 @@ void ui_but_string_get_ex(uiBut *but,
/* uiBut.custom_data points to data this tab represents (e.g. workspace).
* uiBut.rnapoin/prop store an active value (e.g. active workspace). */
- RNA_pointer_create(but->rnapoin.id.data, ptr_type, but->custom_data, &ptr);
+ RNA_pointer_create(but->rnapoin.owner_id, ptr_type, but->custom_data, &ptr);
buf = RNA_struct_name_get_alloc(&ptr, str, maxlen, &buf_len);
}
else if (type == PROP_STRING) {
@@ -2822,7 +2822,7 @@ bool ui_but_string_set(bContext *C, uiBut *but, const char *str)
/* uiBut.custom_data points to data this tab represents (e.g. workspace).
* uiBut.rnapoin/prop store an active value (e.g. active workspace). */
- RNA_pointer_create(but->rnapoin.id.data, ptr_type, but->custom_data, &ptr);
+ RNA_pointer_create(but->rnapoin.owner_id, ptr_type, but->custom_data, &ptr);
prop = RNA_struct_name_property(ptr_type);
if (RNA_property_editable(&ptr, prop)) {
RNA_property_string_set(&ptr, prop, str);
@@ -3586,6 +3586,14 @@ static uiBut *ui_def_but(uiBlock *block,
(a1 != 0.0f && a1 != 1.0f)) == false);
}
+ /* Number buttons must have a click-step,
+ * assert instead of correcting the value to ensure the caller knows what they're doing. */
+ if ((type & BUTTYPE) == UI_BTYPE_NUM) {
+ if (ELEM((type & UI_BUT_POIN_TYPES), UI_BUT_POIN_CHAR, UI_BUT_POIN_SHORT, UI_BUT_POIN_INT)) {
+ BLI_assert((int)a1 > 0);
+ }
+ }
+
if (type & UI_BUT_POIN_TYPES) { /* a pointer is required */
if (poin == NULL) {
BLI_assert(0);
diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c
index 4d87cc22ef2..168c6051327 100644
--- a/source/blender/editors/interface/interface_anim.c
+++ b/source/blender/editors/interface/interface_anim.c
@@ -228,7 +228,7 @@ bool ui_but_anim_expression_create(uiBut *but, const char *str)
/* make sure we have animdata for this */
/* FIXME: until materials can be handled by depsgraph,
* don't allow drivers to be created for them */
- id = (ID *)but->rnapoin.id.data;
+ id = but->rnapoin.owner_id;
if ((id == NULL) || (GS(id->name) == ID_MA) || (GS(id->name) == ID_TE)) {
if (G.debug & G_DEBUG) {
printf("ERROR: create expression failed - invalid data-block for adding drivers (%p)\n", id);
@@ -314,7 +314,7 @@ void ui_but_anim_autokey(bContext *C, uiBut *but, Scene *scene, float cfra)
}
}
else {
- id = but->rnapoin.id.data;
+ id = but->rnapoin.owner_id;
/* TODO: this should probably respect the keyingset only option for anim */
if (autokeyframe_cfra_can_key(scene, id)) {
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 22b75da4968..580ff527bf6 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -176,11 +176,21 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg)
UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT);
UI_block_direction_set(block, UI_DIR_CENTER_Y);
- layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style);
-
+ layout = UI_block_layout(block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ 0,
+ 0,
+ U.widget_unit * 10,
+ U.widget_unit * 2,
+ 0,
+ style);
+
+ uiItemL(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"), ICON_HAND);
uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE);
- UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26});
+ UI_block_bounds_set_popup(
+ block, 6 * U.dpi_fac, (const int[2]){-100 * U.dpi_fac, 36 * U.dpi_fac});
shortcut_free_operator_property(prop);
@@ -227,11 +237,21 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg)
UI_block_func_handle_set(block, but_shortcut_name_func, but);
UI_block_direction_set(block, UI_DIR_CENTER_Y);
- layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style);
-
+ layout = UI_block_layout(block,
+ UI_LAYOUT_VERTICAL,
+ UI_LAYOUT_PANEL,
+ 0,
+ 0,
+ U.widget_unit * 10,
+ U.widget_unit * 2,
+ 0,
+ style);
+
+ uiItemL(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Assign Shortcut"), ICON_HAND);
uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE);
- UI_block_bounds_set_popup(block, 6, (const int[2]){-50, 26});
+ UI_block_bounds_set_popup(
+ block, 6 * U.dpi_fac, (const int[2]){-100 * U.dpi_fac, 36 * U.dpi_fac});
#ifdef USE_KEYMAP_ADD_HACK
g_kmi_id_hack = kmi_id;
@@ -470,8 +490,9 @@ static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, Pr
bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
{
- /* having this menu for some buttons makes no sense */
- if (but->type == UI_BTYPE_IMAGE) {
+ /* ui_but_is_interactive() may let some buttons through that should not get a context menu - it
+ * doesn't make sense for them. */
+ if (ELEM(but->type, UI_BTYPE_LABEL, UI_BTYPE_IMAGE)) {
return false;
}
@@ -904,7 +925,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
ICON_NONE,
"UI_OT_copy_data_path_button");
- if (ptr->id.data && !is_whole_array &&
+ if (ptr->owner_id && !is_whole_array &&
ELEM(type, PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) {
uiItemO(layout,
CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy As New Driver"),
@@ -1222,7 +1243,7 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa)
sizeof(tmpstr),
"%s" UI_SEP_CHAR_S "%s",
IFACE_("Pin"),
- IFACE_("Shift+Left Mouse"));
+ IFACE_("Shift Left Mouse"));
uiItemR(layout, &ptr, "use_pin", 0, tmpstr, ICON_NONE);
/* evil, force shortcut flag */
@@ -1230,6 +1251,7 @@ void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa)
uiBlock *block = uiLayoutGetBlock(layout);
uiBut *but = block->buttons.last;
but->flag |= UI_BUT_HAS_SEP_CHAR;
+ but->drawflag |= UI_BUT_HAS_SHORTCUT;
}
}
UI_popup_menu_end(C, pup);
diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c
index 76630de96db..b7a0812c5f2 100644
--- a/source/blender/editors/interface/interface_draw.c
+++ b/source/blender/editors/interface/interface_draw.c
@@ -750,7 +750,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar),
/**
* Draw title and text safe areas.
*
- * \Note This functionn is to be used with the 2D dashed shader enabled.
+ * \note This function is to be used with the 2D dashed shader enabled.
*
* \param pos: is a PRIM_FLOAT, 2, GPU_FETCH_FLOAT vertex attribute.
* \param line_origin: is a PRIM_FLOAT, 2, GPU_FETCH_FLOAT vertex attribute.
diff --git a/source/blender/editors/interface/interface_eyedropper_datablock.c b/source/blender/editors/interface/interface_eyedropper_datablock.c
index 658aa4f67f9..336fae45895 100644
--- a/source/blender/editors/interface/interface_eyedropper_datablock.c
+++ b/source/blender/editors/interface/interface_eyedropper_datablock.c
@@ -51,6 +51,7 @@
#include "ED_space_api.h"
#include "ED_screen.h"
#include "ED_view3d.h"
+#include "ED_outliner.h"
#include "interface_intern.h"
#include "interface_eyedropper_intern.h"
@@ -67,6 +68,7 @@ typedef struct DataDropper {
ID *init_id; /* for resetting on cancel */
+ ScrArea *cursor_area; /* Area under the cursor */
ARegionType *art;
void *draw_handle_pixel;
char name[200];
@@ -103,6 +105,7 @@ static int datadropper_init(bContext *C, wmOperator *op)
ddr->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO);
+ ddr->cursor_area = CTX_wm_area(C);
ddr->art = art;
ddr->draw_handle_pixel = ED_region_draw_cb_activate(
art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
@@ -115,7 +118,7 @@ static int datadropper_init(bContext *C, wmOperator *op)
ddr->idcode_name = TIP_(BKE_idcode_to_name(ddr->idcode));
PointerRNA ptr = RNA_property_pointer_get(&ddr->ptr, ddr->prop);
- ddr->init_id = ptr.id.data;
+ ddr->init_id = ptr.owner_id;
return true;
}
@@ -141,7 +144,7 @@ static void datadropper_exit(bContext *C, wmOperator *op)
/* *** datadropper id helper functions *** */
/**
- * \brief get the ID from the screen.
+ * \brief get the ID from the 3D view or outliner.
*/
static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id)
{
@@ -155,7 +158,7 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
ddr->name[0] = '\0';
if (sa) {
- if (sa->spacetype == SPACE_VIEW3D) {
+ if (ELEM(sa->spacetype, SPACE_VIEW3D, SPACE_OUTLINER)) {
ARegion *ar = BKE_area_find_region_xy(sa, RGN_TYPE_WINDOW, mx, my);
if (ar) {
const int mval[2] = {mx - ar->winrct.xmin, my - ar->winrct.ymin};
@@ -167,7 +170,13 @@ static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int
/* grr, always draw else we leave stale text */
ED_region_tag_redraw(ar);
- base = ED_view3d_give_base_under_cursor(C, mval);
+ if (sa->spacetype == SPACE_VIEW3D) {
+ base = ED_view3d_give_base_under_cursor(C, mval);
+ }
+ else {
+ base = ED_outliner_give_base_under_cursor(C, mval);
+ }
+
if (base) {
Object *ob = base->object;
ID *id = NULL;
@@ -213,7 +222,7 @@ static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id)
ptr_value = RNA_property_pointer_get(&ddr->ptr, ddr->prop);
- return (ptr_value.id.data == id);
+ return (ptr_value.owner_id == id);
}
/* single point sample & set */
@@ -232,6 +241,36 @@ static void datadropper_cancel(bContext *C, wmOperator *op)
datadropper_exit(C, op);
}
+/* To switch the draw callback when region under mouse event changes */
+static void datadropper_set_draw_callback_region(bContext *C,
+ DataDropper *ddr,
+ const int mx,
+ const int my)
+{
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *sa = BKE_screen_find_area_xy(screen, -1, mx, my);
+
+ if (sa) {
+ /* If spacetype changed */
+ if (sa->spacetype != ddr->cursor_area->spacetype) {
+ /* Remove old callback */
+ ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
+
+ /* Redraw old area */
+ ARegion *ar = BKE_area_find_region_type(ddr->cursor_area, RGN_TYPE_WINDOW);
+ ED_region_tag_redraw(ar);
+
+ /* Set draw callback in new region */
+ ARegionType *art = BKE_regiontype_from_id(sa->type, RGN_TYPE_WINDOW);
+
+ ddr->cursor_area = sa;
+ ddr->art = art;
+ ddr->draw_handle_pixel = ED_region_draw_cb_activate(
+ art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
+ }
+ }
+}
+
/* main modal status check */
static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
@@ -260,6 +299,10 @@ static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
else if (event->type == MOUSEMOVE) {
ID *id = NULL;
+
+ /* Set the region for eyedropper cursor text drawing */
+ datadropper_set_draw_callback_region(C, ddr, event->x, event->y);
+
datadropper_id_sample_pt(C, ddr, event->x, event->y, &id);
}
diff --git a/source/blender/editors/interface/interface_eyedropper_driver.c b/source/blender/editors/interface/interface_eyedropper_driver.c
index c1aee190cd3..e6fc52bc3bc 100644
--- a/source/blender/editors/interface/interface_eyedropper_driver.c
+++ b/source/blender/editors/interface/interface_eyedropper_driver.c
@@ -116,10 +116,10 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve
/* Now create driver(s) */
if (target_path && dst_path) {
int success = ANIM_add_driver_with_target(op->reports,
- ddr->ptr.id.data,
+ ddr->ptr.owner_id,
dst_path,
ddr->index,
- target_ptr->id.data,
+ target_ptr->owner_id,
target_path,
target_index,
flag,
@@ -130,7 +130,7 @@ static void driverdropper_sample(bContext *C, wmOperator *op, const wmEvent *eve
/* send updates */
UI_context_update_anim_flag(C);
DEG_relations_tag_update(CTX_data_main(C));
- DEG_id_tag_update(ddr->ptr.id.data, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(ddr->ptr.owner_id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_ANIMATION | ND_FCURVES_ORDER, NULL); // XXX
}
}
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 0cb0dbdc85c..55980099116 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -757,7 +757,7 @@ static void ui_apply_but_undo(uiBut *but)
}
/* Optionally override undo when undo system doesn't support storing properties. */
- if (but->rnapoin.id.data) {
+ if (but->rnapoin.owner_id) {
/* Exception for renaming ID data, we always need undo pushes in this case,
* because undo systems track data by their ID, see: T67002. */
extern PropertyRNA rna_ID_name;
@@ -765,7 +765,7 @@ static void ui_apply_but_undo(uiBut *but)
/* pass */
}
else {
- ID *id = but->rnapoin.id.data;
+ ID *id = but->rnapoin.owner_id;
if (!ED_undo_is_legacy_compatible_for_property(but->block->evil_C, id)) {
str = "";
}
@@ -1558,7 +1558,7 @@ static bool ui_selectcontext_begin(bContext *C, uiBut *but, uiSelectContextStore
if (use_path_from_id) {
/* Path relative to ID. */
lprop = NULL;
- RNA_id_pointer_create(link->ptr.id.data, &idptr);
+ RNA_id_pointer_create(link->ptr.owner_id, &idptr);
RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
}
else if (path) {
@@ -2760,7 +2760,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con
startx += UI_DPI_ICON_SIZE / aspect;
}
}
- /* but this extra .05 makes clicks inbetween characters feel nicer */
+ /* But this extra .05 makes clicks in between characters feel nicer. */
startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit) / aspect;
/* mouse dragged outside the widget to the left */
@@ -4800,18 +4800,19 @@ static int ui_do_but_NUM(
if (click) {
/* we can click on the side arrows to increment/decrement,
* or click inside to edit the value directly */
- const float softmin = but->softmin;
- const float softmax = but->softmax;
if (!ui_but_is_float(but)) {
/* Integer Value. */
if (but->drawflag & (UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT)) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
const int value_step = (int)but->a1;
BLI_assert(value_step > 0);
+ const int softmin = round_fl_to_int_clamp(but->softmin);
+ const int softmax = round_fl_to_int_clamp(but->softmax);
const double value_test = (but->drawflag & UI_BUT_ACTIVE_LEFT) ?
- (double)max_ii((int)softmin, (int)data->value - value_step) :
- (double)min_ii((int)softmax, (int)data->value + value_step);
+ (double)max_ii(softmin, (int)data->value - value_step) :
+ (double)min_ii(softmax, (int)data->value + value_step);
if (value_test != data->value) {
data->value = (double)value_test;
}
@@ -4828,11 +4829,14 @@ static int ui_do_but_NUM(
/* Float Value. */
if (but->drawflag & (UI_BUT_ACTIVE_LEFT | UI_BUT_ACTIVE_RIGHT)) {
button_activate_state(C, but, BUTTON_STATE_NUM_EDITING);
+
const double value_step = (double)but->a1 * UI_PRECISION_FLOAT_SCALE;
BLI_assert(value_step > 0.0f);
const double value_test = (but->drawflag & UI_BUT_ACTIVE_LEFT) ?
- (double)max_ff(softmin, (float)(data->value - value_step)) :
- (double)min_ff(softmax, (float)(data->value + value_step));
+ (double)max_ff(but->softmin,
+ (float)(data->value - value_step)) :
+ (double)min_ff(but->softmax,
+ (float)(data->value + value_step));
if (value_test != data->value) {
data->value = value_test;
}
@@ -5484,7 +5488,7 @@ static bool ui_numedit_but_UNITVEC(
static void ui_palette_set_active(uiBut *but)
{
if ((int)(but->a1) == UI_PALETTE_COLOR) {
- Palette *palette = but->rnapoin.id.data;
+ Palette *palette = (Palette *)but->rnapoin.owner_id;
PaletteColor *color = but->rnapoin.data;
palette->active_color = BLI_findindex(&palette->colors, color);
}
@@ -5547,7 +5551,7 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co
}
else if ((int)(but->a1) == UI_PALETTE_COLOR && event->type == DELKEY &&
event->val == KM_PRESS) {
- Palette *palette = but->rnapoin.id.data;
+ Palette *palette = (Palette *)but->rnapoin.owner_id;
PaletteColor *color = but->rnapoin.data;
BKE_palette_color_remove(palette, color);
@@ -8184,7 +8188,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but)
else {
/* Do this so we can still mouse-up, closing the menu and running the button.
* This is nice to support but there are times when the button gets left pressed.
- * Keep disavled for now. */
+ * Keep disabled for now. */
WM_event_remove_timer(data->wm, data->window, data->hold_action_timer);
data->hold_action_timer = NULL;
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index e9aa18394fa..7ada4755a64 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -154,8 +154,8 @@ typedef struct IconType {
} IconType;
/* ******************* STATIC LOCAL VARS ******************* */
-/* static here to cache results of icon directory scan, so it's not
- * scanning the filesystem each time the menu is drawn */
+/* Static here to cache results of icon directory scan, so it's not
+ * scanning the file-system each time the menu is drawn. */
static struct ListBase iconfilelist = {NULL, NULL};
static IconTexture icongltex = {{0, 0}, 0, 0, 0, 0.0f, 0.0f};
@@ -317,8 +317,9 @@ static void vicon_keytype_draw_wrapper(
format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
GPU_program_point_size(true);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ immUniform1f("outline_scale", 1.0f);
immUniform2f("ViewportSize", -1.0f, -1.0f);
immBegin(GPU_PRIM_POINTS, 1);
@@ -2136,7 +2137,7 @@ int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big
/* try ID, material, texture or dynapaint slot */
if (RNA_struct_is_ID(ptr->type)) {
- id = ptr->id.data;
+ id = ptr->owner_id;
}
else if (RNA_struct_is_a(ptr->type, &RNA_MaterialSlot)) {
id = RNA_pointer_get(ptr, "material").data;
@@ -2243,6 +2244,8 @@ int UI_idcode_icon_get(const int idcode)
return ICON_FONT_DATA;
case ID_WO:
return ICON_WORLD_DATA;
+ case ID_WS:
+ return ICON_WORKSPACE;
default:
return ICON_NONE;
}
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 78eed98eb77..529cb0712df 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -1180,11 +1180,6 @@ static uiBut *uiItemFullO_ptr_ex(uiLayout *layout,
assert(but->optype != NULL);
- /* text alignment for toolbar buttons */
- if ((layout->root->type == UI_LAYOUT_TOOLBAR) && !icon) {
- but->drawflag |= UI_BUT_TEXT_LEFT;
- }
-
if (flag & UI_ITEM_R_NO_BG) {
layout->emboss = prev_emboss;
}
@@ -1878,7 +1873,8 @@ void uiItemFullR(uiLayout *layout,
uiBut *but;
} ui_decorate = {
.use_prop_decorate = (((layout->item.flag & UI_ITEM_PROP_DECORATE) != 0) &&
- (use_prop_sep && ptr->id.data && id_can_have_animdata(ptr->id.data))),
+ (use_prop_sep && ptr->owner_id &&
+ id_can_have_animdata(ptr->owner_id))),
};
#endif /* UI_PROP_DECORATE */
@@ -2951,7 +2947,7 @@ void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, const char *name, int icon)
if (ptr && ptr->type) {
if (RNA_struct_is_ID(ptr->type)) {
- UI_but_drag_set_id(but, ptr->id.data);
+ UI_but_drag_set_id(but, ptr->owner_id);
}
}
}
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index 6051bf5ca40..68d21e88211 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -27,7 +27,7 @@
#include "DNA_armature_types.h"
#include "DNA_screen_types.h"
-#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
+#include "DNA_text_types.h"
#include "DNA_object_types.h" /* for OB_DATA_SUPPORT_ID */
#include "BLI_blenlib.h"
@@ -45,7 +45,7 @@
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_screen.h"
-#include "BKE_text.h" /* for UI_OT_reports_to_text */
+#include "BKE_text.h"
#include "IMB_colormanagement.h"
@@ -86,7 +86,7 @@ static bool copy_data_path_button_poll(bContext *C)
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop) {
+ if (ptr.owner_id && ptr.data && prop) {
path = RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
@@ -100,29 +100,33 @@ static bool copy_data_path_button_poll(bContext *C)
static int copy_data_path_button_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
PointerRNA ptr;
PropertyRNA *prop;
char *path;
int index;
+ ID *id;
const bool full_path = RNA_boolean_get(op->ptr, "full_path");
/* try to create driver using property retrieved from UI */
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data != NULL) {
-
+ if (ptr.owner_id != NULL) {
if (full_path) {
-
if (prop) {
- path = RNA_path_full_property_py_ex(&ptr, prop, index, true);
+ path = RNA_path_full_property_py_ex(bmain, &ptr, prop, index, true);
}
else {
- path = RNA_path_full_struct_py(&ptr);
+ path = RNA_path_full_struct_py(bmain, &ptr);
}
}
else {
- path = RNA_path_from_ID_to_property(&ptr, prop);
+ path = RNA_path_from_real_ID_to_property_index(bmain, &ptr, prop, 0, -1, &id);
+
+ if (!path) {
+ path = RNA_path_from_ID_to_property(&ptr, prop);
+ }
}
if (path) {
@@ -171,7 +175,7 @@ static bool copy_as_driver_button_poll(bContext *C)
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop &&
+ if (ptr.owner_id && ptr.data && prop &&
ELEM(RNA_property_type(prop), PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM) &&
(index >= 0 || !RNA_property_array_check(prop))) {
path = RNA_path_from_ID_to_property(&ptr, prop);
@@ -185,8 +189,9 @@ static bool copy_as_driver_button_poll(bContext *C)
return 0;
}
-static int copy_as_driver_button_exec(bContext *C, wmOperator *UNUSED(op))
+static int copy_as_driver_button_exec(bContext *C, wmOperator *op)
{
+ Main *bmain = CTX_data_main(C);
PointerRNA ptr;
PropertyRNA *prop;
int index;
@@ -194,15 +199,20 @@ static int copy_as_driver_button_exec(bContext *C, wmOperator *UNUSED(op))
/* try to create driver using property retrieved from UI */
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- if (ptr.id.data && ptr.data && prop) {
+ if (ptr.owner_id && ptr.data && prop) {
+ ID *id;
int dim = RNA_property_array_dimension(&ptr, prop, NULL);
- char *path = RNA_path_from_ID_to_property_index(&ptr, prop, dim, index);
+ char *path = RNA_path_from_real_ID_to_property_index(bmain, &ptr, prop, dim, index, &id);
if (path) {
- ANIM_copy_as_driver(ptr.id.data, path, RNA_property_identifier(prop));
+ ANIM_copy_as_driver(id, path, RNA_property_identifier(prop));
MEM_freeN(path);
return OPERATOR_FINISHED;
}
+ else {
+ BKE_reportf(op->reports, RPT_ERROR, "Could not compute a valid data path");
+ return OPERATOR_CANCELLED;
+ }
}
return OPERATOR_CANCELLED;
@@ -287,7 +297,7 @@ static void UI_OT_copy_python_command_button(wmOperatorType *ot)
static int operator_button_property_finish(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
/* perform updates required for this property */
RNA_property_update(C, ptr, prop);
@@ -542,7 +552,7 @@ static int override_type_set_button_exec(bContext *C, wmOperator *op)
/* try to reset the nominated setting to its default value */
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- BLI_assert(ptr.id.data != NULL);
+ BLI_assert(ptr.owner_id != NULL);
if (all) {
index = -1;
@@ -605,7 +615,7 @@ static bool override_remove_button_poll(bContext *C)
const int override_status = RNA_property_override_library_status(&ptr, prop, index);
- return (ptr.data && ptr.id.data && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN));
+ return (ptr.data && ptr.owner_id && prop && (override_status & RNA_OVERRIDE_STATUS_OVERRIDDEN));
}
static int override_remove_button_exec(bContext *C, wmOperator *op)
@@ -619,7 +629,7 @@ static int override_remove_button_exec(bContext *C, wmOperator *op)
/* try to reset the nominated setting to its default value */
UI_context_active_but_prop_get(C, &ptr, &prop, &index);
- ID *id = ptr.id.data;
+ ID *id = ptr.owner_id;
IDOverrideLibraryProperty *oprop = RNA_property_override_property_find(&ptr, prop);
BLI_assert(oprop != NULL);
BLI_assert(id != NULL && id->override_library != NULL);
@@ -629,8 +639,9 @@ static int override_remove_button_exec(bContext *C, wmOperator *op)
/* We need source (i.e. linked data) to restore values of deleted overrides...
* If this is an override template, we obviously do not need to restore anything. */
if (!is_template) {
+ PropertyRNA *src_prop;
RNA_id_pointer_create(id->override_library->reference, &id_refptr);
- if (!RNA_path_resolve(&id_refptr, oprop->rna_path, &src, NULL)) {
+ if (!RNA_path_resolve_property(&id_refptr, oprop->rna_path, &src, &src_prop)) {
BLI_assert(0 && "Failed to create matching source (linked data) RNA pointer");
}
}
@@ -720,7 +731,7 @@ bool UI_context_copy_to_selected_list(bContext *C,
CollectionPointerLink *link;
for (link = lb.first; link; link = link->next) {
bPoseChannel *pchan = link->ptr.data;
- RNA_pointer_create(link->ptr.id.data, &RNA_Bone, pchan->bone, &link->ptr);
+ RNA_pointer_create(link->ptr.owner_id, &RNA_Bone, pchan->bone, &link->ptr);
}
}
@@ -739,7 +750,7 @@ bool UI_context_copy_to_selected_list(bContext *C,
/* Get the node we're editing */
if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = ptr->data;
if (nodeFindNode(ntree, sock, &node, NULL)) {
if ((path = RNA_path_resolve_from_type_to_property(ptr, prop, &RNA_Node)) != NULL) {
@@ -773,8 +784,8 @@ bool UI_context_copy_to_selected_list(bContext *C,
*r_lb = lb;
*r_path = path;
}
- else if (ptr->id.data) {
- ID *id = ptr->id.data;
+ else if (ptr->owner_id) {
+ ID *id = ptr->owner_id;
if (GS(id->name) == ID_OB) {
*r_lb = CTX_data_collection_get(C, "selected_editable_objects");
@@ -792,7 +803,7 @@ bool UI_context_copy_to_selected_list(bContext *C,
CollectionPointerLink *link, *link_next;
for (link = lb.first; link; link = link->next) {
- Object *ob = link->ptr.id.data;
+ Object *ob = (Object *)link->ptr.owner_id;
if (ob->data) {
ID *id_data = ob->data;
id_data->tag |= LIB_TAG_DOIT;
@@ -800,7 +811,7 @@ bool UI_context_copy_to_selected_list(bContext *C,
}
for (link = lb.first; link; link = link_next) {
- Object *ob = link->ptr.id.data;
+ Object *ob = (Object *)link->ptr.owner_id;
ID *id_data = ob->data;
link_next = link->next;
@@ -872,7 +883,7 @@ static bool copy_to_selected_button(bContext *C, bool all, bool poll)
if (use_path_from_id) {
/* Path relative to ID. */
lprop = NULL;
- RNA_id_pointer_create(link->ptr.id.data, &idptr);
+ RNA_id_pointer_create(link->ptr.owner_id, &idptr);
RNA_path_resolve_property(&idptr, path, &lptr, &lprop);
}
else if (path) {
@@ -982,12 +993,12 @@ static bool jump_to_target_ptr(bContext *C, PointerRNA ptr, const bool poll)
/* Find the containing Object. */
ViewLayer *view_layer = CTX_data_view_layer(C);
Base *base = NULL;
- const short id_type = GS(((ID *)ptr.id.data)->name);
+ const short id_type = GS(ptr.owner_id->name);
if (id_type == ID_OB) {
- base = BKE_view_layer_base_find(view_layer, ptr.id.data);
+ base = BKE_view_layer_base_find(view_layer, (Object *)ptr.owner_id);
}
else if (OB_DATA_SUPPORT_ID(id_type)) {
- base = ED_object_find_first_by_data_id(view_layer, ptr.id.data);
+ base = ED_object_find_first_by_data_id(view_layer, ptr.owner_id);
}
bool ok = false;
@@ -1096,60 +1107,6 @@ static void UI_OT_jump_to_target_button(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Reports to Textblock Operator
- * \{ */
-
-/* FIXME: this is just a temporary operator so that we can see all the reports somewhere
- * when there are too many to display...
- */
-
-static bool reports_to_text_poll(bContext *C)
-{
- return CTX_wm_reports(C) != NULL;
-}
-
-static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
-{
- ReportList *reports = CTX_wm_reports(C);
- Main *bmain = CTX_data_main(C);
- Text *txt;
- char *str;
-
- /* create new text-block to write to */
- txt = BKE_text_add(bmain, "Recent Reports");
-
- /* convert entire list to a display string, and add this to the text-block
- * - if commandline debug option enabled, show debug reports too
- * - otherwise, up to info (which is what users normally see)
- */
- str = BKE_reports_string(reports, (G.debug & G_DEBUG) ? RPT_DEBUG : RPT_INFO);
-
- if (str) {
- BKE_text_write(txt, str);
- MEM_freeN(str);
-
- return OPERATOR_FINISHED;
- }
- else {
- return OPERATOR_CANCELLED;
- }
-}
-
-static void UI_OT_reports_to_textblock(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Reports to Text Block";
- ot->idname = "UI_OT_reports_to_textblock";
- ot->description = "Write the reports ";
-
- /* callbacks */
- ot->poll = reports_to_text_poll;
- ot->exec = reports_to_text_exec;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Edit Python Source Operator
* \{ */
@@ -1750,7 +1707,6 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_override_remove_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
WM_operatortype_append(UI_OT_jump_to_target_button);
- WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
WM_operatortype_append(UI_OT_drop_color);
#ifdef WITH_PYTHON
WM_operatortype_append(UI_OT_editsource);
diff --git a/source/blender/editors/interface/interface_region_popup.c b/source/blender/editors/interface/interface_region_popup.c
index f3e18cc2f24..2073117d51c 100644
--- a/source/blender/editors/interface/interface_region_popup.c
+++ b/source/blender/editors/interface/interface_region_popup.c
@@ -690,9 +690,11 @@ uiBlock *ui_popup_block_refresh(bContext *C,
/* Avoid menu moving down and losing cursor focus by keeping it at
* the same height. */
if (handle->refresh && handle->prev_block_rect.ymax > block->rect.ymax) {
- float offset = handle->prev_block_rect.ymax - block->rect.ymax;
- UI_block_translate(block, 0, offset);
- block->rect.ymin = handle->prev_block_rect.ymin;
+ if (block->bounds_type != UI_BLOCK_BOUNDS_POPUP_CENTER) {
+ float offset = handle->prev_block_rect.ymax - block->rect.ymax;
+ UI_block_translate(block, 0, offset);
+ block->rect.ymin = handle->prev_block_rect.ymin;
+ }
}
handle->prev_block_rect = block->rect;
diff --git a/source/blender/editors/interface/interface_region_tooltip.c b/source/blender/editors/interface/interface_region_tooltip.c
index 6aad9e41e7d..7387fe5eb1c 100644
--- a/source/blender/editors/interface/interface_region_tooltip.c
+++ b/source/blender/editors/interface/interface_region_tooltip.c
@@ -765,8 +765,8 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
- if (but->rnapoin.id.data) {
- const ID *id = but->rnapoin.id.data;
+ if (but->rnapoin.owner_id) {
+ const ID *id = but->rnapoin.owner_id;
if (ID_IS_LINKED(id)) {
uiTooltipField *field = text_field_add(data,
&(uiTooltipFormat){
@@ -847,7 +847,7 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
}
}
- if (but->rnapoin.id.data) {
+ if (but->rnapoin.owner_id) {
uiTooltipField *field = text_field_add(data,
&(uiTooltipFormat){
.style = UI_TIP_STYLE_MONO,
@@ -860,10 +860,10 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but)
/* move ownership (no need for re-alloc) */
if (but->rnaprop) {
field->text = RNA_path_full_property_py_ex(
- &but->rnapoin, but->rnaprop, but->rnaindex, true);
+ CTX_data_main(C), &but->rnapoin, but->rnaprop, but->rnaindex, true);
}
else {
- field->text = RNA_path_full_struct_py(&but->rnapoin);
+ field->text = RNA_path_full_struct_py(CTX_data_main(C), &but->rnapoin);
}
}
}
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 37eb1770f68..f53bef877c4 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -121,7 +121,7 @@ static void template_add_button_search_menu(const bContext *C,
{
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;
- const ID *idfrom = ptr->id.data;
+ const ID *idfrom = ptr->owner_id;
const StructRNA *type = active_ptr.type ? active_ptr.type : RNA_property_pointer_type(ptr, prop);
uiBut *but;
@@ -310,7 +310,7 @@ static bool id_search_add(const bContext *C,
uiSearchItems *items,
ID *id)
{
- ID *id_from = template_ui->ptr.id.data;
+ ID *id_from = template_ui->ptr.owner_id;
if (!((flag & PROP_ID_SELF_CHECK) && id == id_from)) {
@@ -401,7 +401,7 @@ static void id_search_cb_objects_from_scene(const bContext *C,
TemplateID *template_ui = (TemplateID *)arg_template;
ListBase *lb = template_ui->idlb;
Scene *scene = NULL;
- ID *id_from = template_ui->ptr.id.data;
+ ID *id_from = template_ui->ptr.owner_id;
if (id_from && GS(id_from->name) == ID_SCE) {
scene = (Scene *)id_from;
@@ -538,7 +538,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
break;
case UI_ID_OVERRIDE:
if (id && id->override_library) {
- BKE_override_library_free(&id->override_library);
+ BKE_override_library_free(&id->override_library, true);
/* reassign to get get proper updates/notifiers */
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr, NULL);
@@ -667,7 +667,7 @@ static uiBut *template_id_def_new_but(uiBlock *block,
const bool use_tab_but,
int but_height)
{
- ID *idfrom = template_ui->ptr.id.data;
+ ID *idfrom = template_ui->ptr.owner_id;
uiBut *but;
const int w = id ? UI_UNIT_X : id_open ? UI_UNIT_X * 3 : UI_UNIT_X * 6;
const int but_type = use_tab_but ? UI_BTYPE_TAB : UI_BTYPE_BUT;
@@ -769,7 +769,7 @@ static void template_ID(bContext *C,
idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop);
id = idptr.data;
- idfrom = template_ui->ptr.id.data;
+ idfrom = template_ui->ptr.owner_id;
// lb = template_ui->idlb;
block = uiLayoutGetBlock(layout);
@@ -2037,7 +2037,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
return NULL;
}
- ob = ptr->id.data;
+ ob = (Object *)ptr->owner_id;
md = ptr->data;
if (!ob || !(GS(ob->id.name) == ID_OB)) {
@@ -2179,7 +2179,7 @@ uiLayout *uiTemplateGpencilModifier(uiLayout *layout, bContext *UNUSED(C), Point
return NULL;
}
- ob = ptr->id.data;
+ ob = (Object *)ptr->owner_id;
md = ptr->data;
if (!ob || !(GS(ob->id.name) == ID_OB)) {
@@ -2297,7 +2297,7 @@ uiLayout *uiTemplateShaderFx(uiLayout *layout, bContext *UNUSED(C), PointerRNA *
return NULL;
}
- ob = ptr->id.data;
+ ob = (Object *)ptr->owner_id;
fx = ptr->data;
if (!ob || !(GS(ob->id.name) == ID_OB)) {
@@ -2523,7 +2523,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
/* enabled */
UI_block_emboss_set(block, UI_EMBOSS_NONE);
- uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_HIDE_ON : ICON_HIDE_OFF);
+ uiItemR(row, &ptr, "mute", 0, "", 0);
UI_block_emboss_set(block, UI_EMBOSS);
uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
@@ -2579,7 +2579,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
return NULL;
}
- ob = ptr->id.data;
+ ob = (Object *)ptr->owner_id;
con = ptr->data;
if (!ob || !(GS(ob->id.name) == ID_OB)) {
@@ -3098,7 +3098,7 @@ static void colorband_buttons_layout(uiLayout *layout,
float ys = butr->ymin;
PointerRNA ptr;
- RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRamp, coba, &ptr);
+ RNA_pointer_create(cb->ptr.owner_id, &RNA_ColorRamp, coba, &ptr);
split = uiLayoutSplit(layout, 0.4f, false);
@@ -3190,7 +3190,7 @@ static void colorband_buttons_layout(uiLayout *layout,
if (coba->tot) {
CBData *cbd = coba->data + coba->cur;
- RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
+ RNA_pointer_create(cb->ptr.owner_id, &RNA_ColorRampElement, cbd, &ptr);
if (!expand) {
split = uiLayoutSplit(layout, 0.3f, false);
@@ -3207,7 +3207,7 @@ static void colorband_buttons_layout(uiLayout *layout,
&coba->cur,
0.0,
(float)(MAX2(0, coba->tot - 1)),
- 0,
+ 1,
0,
TIP_("Choose active color stop"));
row = uiLayoutRow(split, false);
@@ -3237,7 +3237,7 @@ static void colorband_buttons_layout(uiLayout *layout,
&coba->cur,
0.0,
(float)(MAX2(0, coba->tot - 1)),
- 0,
+ 1,
0,
TIP_("Choose active color stop"));
row = uiLayoutRow(subsplit, false);
@@ -3283,7 +3283,7 @@ void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname
block = uiLayoutAbsoluteBlock(layout);
- id = cptr.id.data;
+ id = cptr.owner_id;
UI_block_lock_set(block, (id && ID_IS_LINKED(id)), ERROR_LIBDATA_MESSAGE);
colorband_buttons_layout(layout, block, cptr.data, &rect, cb, expand);
@@ -3745,12 +3745,11 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v)
float width = 8 * UI_UNIT_X;
block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
-
- /* use this for a fake extra empty space around the buttons */
- uiDefBut(block, UI_BTYPE_LABEL, 0, "", -4, 16, width + 8, 6 * UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
+ UI_block_flag_enable(block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_MOVEMOUSE_QUIT);
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
bt = uiDefButBitI(block,
- UI_BTYPE_TOGGLE,
+ UI_BTYPE_CHECKBOX,
CUMA_DO_CLIP,
1,
IFACE_("Use Clipping"),
@@ -3770,7 +3769,7 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v)
uiDefButF(block,
UI_BTYPE_NUM,
0,
- IFACE_("Min X "),
+ IFACE_("Min X:"),
0,
4 * UI_UNIT_Y,
width,
@@ -3784,7 +3783,7 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v)
uiDefButF(block,
UI_BTYPE_NUM,
0,
- IFACE_("Min Y "),
+ IFACE_("Min Y:"),
0,
3 * UI_UNIT_Y,
width,
@@ -3798,7 +3797,7 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v)
uiDefButF(block,
UI_BTYPE_NUM,
0,
- IFACE_("Max X "),
+ IFACE_("Max X:"),
0,
2 * UI_UNIT_Y,
width,
@@ -3812,7 +3811,7 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v)
uiDefButF(block,
UI_BTYPE_NUM,
0,
- IFACE_("Max Y "),
+ IFACE_("Max Y:"),
0,
UI_UNIT_Y,
width,
@@ -3824,7 +3823,8 @@ static uiBlock *curvemap_clipping_func(bContext *C, ARegion *ar, void *cumap_v)
2,
"");
- UI_block_direction_set(block, UI_DIR_RIGHT);
+ UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
+ UI_block_direction_set(block, UI_DIR_DOWN);
return block;
}
@@ -4405,7 +4405,7 @@ void uiTemplateCurveMapping(uiLayout *layout,
cb->ptr = *ptr;
cb->prop = prop;
- id = cptr.id.data;
+ id = cptr.owner_id;
UI_block_lock_set(block, (id && ID_IS_LINKED(id)), ERROR_LIBDATA_MESSAGE);
curvemap_buttons_layout(layout, &cptr, type, levels, brush, neg_slope, tone, cb);
@@ -6378,7 +6378,7 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
if (reports->list.first != reports->list.last) {
uiDefIconButO(block,
UI_BTYPE_BUT,
- "UI_OT_reports_to_textblock",
+ "SCREEN_OT_info_log_show",
WM_OP_INVOKE_REGION_WIN,
icon,
2,
@@ -6392,22 +6392,17 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
block, UI_BTYPE_LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
}
- UI_block_emboss_set(block, UI_EMBOSS);
-
- uiDefBut(block,
- UI_BTYPE_LABEL,
- 0,
- report->message,
- UI_UNIT_X + 5,
- 0,
- UI_UNIT_X + width,
- UI_UNIT_Y,
- NULL,
- 0.0f,
- 0.0f,
- 0,
- 0,
- "");
+ but = uiDefButO(block,
+ UI_BTYPE_BUT,
+ "SCREEN_OT_info_log_show",
+ WM_OP_INVOKE_REGION_WIN,
+ report->message,
+ UI_UNIT_X + 5,
+ 0,
+ UI_UNIT_X + width,
+ UI_UNIT_Y,
+ "Show in Info Log");
+ rgba_float_to_uchar(but->col, rti->col);
}
void uiTemplateInputStatus(uiLayout *layout, struct bContext *C)
@@ -6627,7 +6622,7 @@ static uiBlock *component_menu(bContext *C, ARegion *ar, void *args_v)
uiItemR(layout, &args->ptr, args->propname, UI_ITEM_R_EXPAND, "", ICON_NONE);
- UI_block_bounds_set_normal(block, 6);
+ UI_block_bounds_set_normal(block, 0.3f * U.widget_unit);
UI_block_direction_set(block, UI_DIR_DOWN);
return block;
diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c
index 9c8787d002f..63e382e2280 100644
--- a/source/blender/editors/interface/interface_utils.c
+++ b/source/blender/editors/interface/interface_utils.c
@@ -405,7 +405,7 @@ void ui_rna_collection_search_cb(const struct bContext *C,
RNA_PROP_BEGIN (&data->search_ptr, itemptr, data->search_prop) {
if (flag & PROP_ID_SELF_CHECK) {
- if (itemptr.data == data->target_ptr.id.data) {
+ if (itemptr.data == data->target_ptr.owner_id) {
continue;
}
}
@@ -566,7 +566,7 @@ int UI_calc_float_precision(int prec, double value)
bool UI_but_online_manual_id(const uiBut *but, char *r_str, size_t maxlength)
{
- if (but->rnapoin.id.data && but->rnapoin.data && but->rnaprop) {
+ if (but->rnapoin.owner_id && but->rnapoin.data && but->rnaprop) {
BLI_snprintf(r_str,
maxlength,
"%s.%s",
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c
index 9c4d628cec5..8d22c5b85bb 100644
--- a/source/blender/editors/interface/interface_widgets.c
+++ b/source/blender/editors/interface/interface_widgets.c
@@ -2188,7 +2188,7 @@ static void widget_draw_text(const uiFontStyle *fstyle,
drawstr_right = strrchr(drawstr + but->ofs, ':');
if (drawstr_right) {
drawstr_right++;
- drawstr_left_len = (drawstr_right - drawstr);
+ drawstr_left_len = (drawstr_right - drawstr - 1);
while (*drawstr_right == ' ') {
drawstr_right++;
@@ -2587,6 +2587,10 @@ static void widget_state(uiWidgetType *wt, int state, int drawflag)
}
}
else {
+ if (state & UI_BUT_ACTIVE_DEFAULT) {
+ copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel);
+ copy_v4_v4_uchar(wt->wcol.text, wt->wcol.text_sel);
+ }
if (color_blend != NULL) {
widget_state_blend(wt->wcol.inner, color_blend, wcol_state->blend);
}
@@ -2709,10 +2713,10 @@ static void widget_state_menu_item(uiWidgetType *wt, int state, int UNUSED(drawf
/* active and disabled (not so common) */
if ((state & UI_BUT_DISABLED) && (state & UI_ACTIVE)) {
- widget_state_blend(wt->wcol.text, wt->wcol.text_sel, 0.5f);
/* draw the backdrop at low alpha, helps navigating with keys
* when disabled items are active */
- copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel);
+ wt->wcol.text[3] = 128;
+ widget_state_blend(wt->wcol.inner, wt->wcol.text, 0.5f);
wt->wcol.inner[3] = 64;
}
else {
@@ -3268,20 +3272,6 @@ static void ui_draw_but_HSV_v(uiBut *but, const rcti *rect)
ui_hsv_cursor(x, y);
}
-/* Generic round-box drawing. */
-static void ui_draw_roundbox(const rcti *rect, const float rad, const uiWidgetColors *wcol)
-{
- uiWidgetBase wtb;
- widget_init(&wtb);
- round_box_edges(&wtb, UI_CNR_ALL, rect, rad);
- widgetbase_draw(&wtb, wcol);
-
- /* We are drawing on top of widget bases. Flush cache. */
- GPU_blend(true);
- UI_widgetbase_draw_cache_flush();
- GPU_blend(false);
-}
-
/* ************ separator, for menus etc ***************** */
static void ui_draw_separator(const rcti *rect, const uiWidgetColors *wcol)
{
@@ -3802,7 +3792,7 @@ static void widget_swatch(
widgetbase_draw_ex(&wtb, wcol, show_alpha_checkers);
if (but->a1 == UI_PALETTE_COLOR &&
- ((Palette *)but->rnapoin.id.data)->active_color == (int)but->a2) {
+ ((Palette *)but->rnapoin.owner_id)->active_color == (int)but->a2) {
float width = rect->xmax - rect->xmin;
float height = rect->ymax - rect->ymin;
/* find color luminance and change it slightly */
@@ -4497,10 +4487,6 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
const uiFontStyle *fstyle = &style->widget;
uiWidgetType *wt = NULL;
-#ifdef USE_UI_POPOVER_ONCE
- const rcti rect_orig = *rect;
-#endif
-
/* handle menus separately */
if (but->dt == UI_EMBOSS_PULLDOWN) {
switch (but->type) {
@@ -4786,6 +4772,14 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
ui_widget_color_disabled(wt);
}
+#ifdef USE_UI_POPOVER_ONCE
+ if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
+ if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
+ state |= UI_BUT_ACTIVE_DEFAULT;
+ }
+ }
+#endif
+
wt->state(wt, state, drawflag);
if (wt->custom) {
wt->custom(but, &wt->wcol, rect, state, roundboxalign);
@@ -4798,42 +4792,10 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct
GPU_blend(true);
}
- bool show_semi_highlight = false;
-
-#ifdef USE_UI_POPOVER_ONCE
- if (but->block->flag & UI_BLOCK_POPOVER_ONCE) {
- if ((state & UI_ACTIVE) && ui_but_is_popover_once_compat(but)) {
- show_semi_highlight = true;
- }
- }
-#endif
- if (but->flag & UI_BUT_ACTIVE_DEFAULT) {
- show_semi_highlight = true;
- }
-
- if (show_semi_highlight) {
- uiWidgetType wt_back = *wt;
- uiWidgetType *wt_temp = widget_type(UI_WTYPE_MENU_ITEM);
- wt_temp->state(wt_temp, state, drawflag);
- copy_v4_v4_uchar(wt->wcol.inner, wt->wcol.inner_sel);
- wt->wcol.inner[3] = 128;
- wt->wcol.roundness = 0.5f;
- ui_draw_roundbox(&rect_orig,
- 0.25f * min_ff(BLI_rcti_size_x(&rect_orig), BLI_rcti_size_y(&rect_orig)),
- &wt_temp->wcol);
- *wt = wt_back;
- }
-
wt->text(fstyle, &wt->wcol, but, rect);
if (disabled) {
GPU_blend(false);
}
-
- // if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) {
- // if (but->dt != UI_EMBOSS_PULLDOWN) {
- // widget_disabled(&disablerect);
- // }
- // }
}
}
diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c
index 1e74ee50dab..93a93fb6918 100644
--- a/source/blender/editors/interface/resources.c
+++ b/source/blender/editors/interface/resources.c
@@ -794,6 +794,10 @@ const uchar *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colorid)
cp = ts->selected_highlight;
break;
+ case TH_SELECT_ACTIVE:
+ cp = ts->active;
+ break;
+
case TH_SELECTED_OBJECT:
cp = ts->selected_object;
break;
diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c
index f32fcffabd4..032fb7e4cc2 100644
--- a/source/blender/editors/interface/view2d_ops.c
+++ b/source/blender/editors/interface/view2d_ops.c
@@ -1844,7 +1844,7 @@ static void scroller_activate_init(bContext *C,
*/
scrollers = UI_view2d_scrollers_calc(v2d, NULL);
- /* use a union of 'cur' & 'tot' incase the current view is far outside 'tot'. In this cases
+ /* Use a union of 'cur' & 'tot' in case the current view is far outside 'tot'. In this cases
* moving the scroll bars has far too little effect and the view can get stuck T31476. */
tot_cur_union = v2d->tot;
BLI_rctf_union(&tot_cur_union, &v2d->cur);
diff --git a/source/blender/editors/mask/mask_shapekey.c b/source/blender/editors/mask/mask_shapekey.c
index edc22943124..1abe805192d 100644
--- a/source/blender/editors/mask/mask_shapekey.c
+++ b/source/blender/editors/mask/mask_shapekey.c
@@ -81,6 +81,7 @@ void MASK_OT_shape_key_insert(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Insert Shape Key";
+ ot->description = "Insert mask shape keyframe for active mask layer at the current frame";
ot->idname = "MASK_OT_shape_key_insert";
/* api callbacks */
@@ -129,6 +130,7 @@ void MASK_OT_shape_key_clear(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Clear Shape Key";
+ ot->description = "Remove mask shape keyframe for active mask layer at the current frame";
ot->idname = "MASK_OT_shape_key_clear";
/* api callbacks */
diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt
index 9a779db4812..d7d020ae19d 100644
--- a/source/blender/editors/mesh/CMakeLists.txt
+++ b/source/blender/editors/mesh/CMakeLists.txt
@@ -43,6 +43,7 @@ set(SRC
editface.c
editmesh_add.c
editmesh_add_gizmo.c
+ editmesh_automerge.c
editmesh_bevel.c
editmesh_bisect.c
editmesh_extrude.c
diff --git a/source/blender/editors/mesh/editmesh_automerge.c b/source/blender/editors/mesh/editmesh_automerge.c
new file mode 100644
index 00000000000..82f53aafad8
--- /dev/null
+++ b/source/blender/editors/mesh/editmesh_automerge.c
@@ -0,0 +1,517 @@
+/*
+ * 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) 2019 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup edmesh
+ *
+ * Utility functions for merging geometry once transform has finished:
+ *
+ * - #EDBM_automerge
+ * - #EDBM_automerge_and_split
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_bitmap.h"
+#include "BLI_math.h"
+#include "BLI_sort.h"
+
+#include "BKE_bvhutils.h"
+#include "BKE_editmesh.h"
+
+#include "WM_api.h"
+
+#include "ED_mesh.h"
+#include "ED_screen.h"
+#include "ED_transform.h"
+
+#include "DNA_object_types.h"
+
+#include "DEG_depsgraph.h"
+
+/* use bmesh operator flags for a few operators */
+#define BMO_ELE_TAG 1
+
+/* -------------------------------------------------------------------- */
+/** \name Auto-Merge Selection
+ *
+ * Used after transform operations.
+ * \{ */
+
+void EDBM_automerge(Object *obedit, bool update, const char hflag, const float dist)
+{
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ int totvert_prev = bm->totvert;
+
+ BMOperator findop, weldop;
+
+ /* Search for doubles among all vertices, but only merge non-VERT_KEEP
+ * vertices into VERT_KEEP vertices. */
+ BMO_op_initf(bm,
+ &findop,
+ BMO_FLAG_DEFAULTS,
+ "find_doubles verts=%av keep_verts=%Hv dist=%f",
+ hflag,
+ dist);
+
+ BMO_op_exec(bm, &findop);
+
+ /* weld the vertices */
+ BMO_op_init(bm, &weldop, BMO_FLAG_DEFAULTS, "weld_verts");
+ BMO_slot_copy(&findop, slots_out, "targetmap.out", &weldop, slots_in, "targetmap");
+ BMO_op_exec(bm, &weldop);
+
+ BMO_op_finish(bm, &findop);
+ BMO_op_finish(bm, &weldop);
+
+ if ((totvert_prev != bm->totvert) && update) {
+ EDBM_update_generic(em, true, true);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Auto-Merge & Split Selection
+ *
+ * Used after transform operations.
+ * \{ */
+
+struct EDBMSplitEdge {
+ BMVert *v;
+ BMEdge *e;
+ float lambda;
+};
+
+struct EDBMSplitBestFaceData {
+ BMEdge **edgenet;
+ int edgenet_len;
+
+ /**
+ * Track the range of vertices in edgenet along the faces normal,
+ * find the lowest since it's most likely to be most co-planar with the face.
+ */
+ float best_face_range_on_normal_axis;
+ BMFace *r_best_face;
+};
+
+struct EDBMSplitEdgeData {
+ BMesh *bm;
+
+ BMEdge *r_edge;
+ float r_lambda;
+};
+
+static bool edbm_vert_pair_share_best_splittable_face_cb(BMFace *f,
+ BMLoop *UNUSED(l_a),
+ BMLoop *UNUSED(l_b),
+ void *userdata)
+{
+ struct EDBMSplitBestFaceData *data = userdata;
+ float no[3], min = FLT_MAX, max = -FLT_MAX;
+ copy_v3_v3(no, f->no);
+
+ BMVert *verts[2] = {NULL};
+ BMEdge **e_iter = &data->edgenet[0];
+ for (int i = data->edgenet_len; i--; e_iter++) {
+ BMIter iter;
+ BMVert *v;
+ BM_ITER_ELEM (v, &iter, *e_iter, BM_VERTS_OF_EDGE) {
+ if (!ELEM(v, verts[0], verts[1])) {
+ float dot = dot_v3v3(v->co, no);
+ if (dot < min) {
+ min = dot;
+ }
+ if (dot > max) {
+ max = dot;
+ }
+ }
+ }
+ verts[0] = (*e_iter)->v1;
+ verts[1] = (*e_iter)->v2;
+ }
+
+ const float test_face_range_on_normal_axis = max - min;
+ if (test_face_range_on_normal_axis < data->best_face_range_on_normal_axis) {
+ data->best_face_range_on_normal_axis = test_face_range_on_normal_axis;
+ data->r_best_face = f;
+ }
+
+ return false;
+}
+
+/* find the best splittable face between the two vertices. */
+static bool edbm_vert_pair_share_splittable_face_cb(BMFace *UNUSED(f),
+ BMLoop *l_a,
+ BMLoop *l_b,
+ void *userdata)
+{
+ float(*data)[3] = userdata;
+ float *v_a_co = data[0];
+ float *v_a_b_dir = data[1];
+
+ float lambda;
+ if (isect_ray_seg_v3(v_a_co, v_a_b_dir, l_a->prev->v->co, l_a->next->v->co, &lambda)) {
+ if (IN_RANGE(lambda, 0.0f, 1.0f)) {
+ return true;
+ }
+ else if (isect_ray_seg_v3(v_a_co, v_a_b_dir, l_b->prev->v->co, l_b->next->v->co, &lambda)) {
+ return IN_RANGE(lambda, 0.0f, 1.0f);
+ }
+ }
+ return false;
+}
+
+static void edbm_automerge_weld_linked_wire_edges_into_linked_faces(BMesh *bm,
+ BMVert *v,
+ BMEdge **r_edgenet[],
+ int *r_edgenet_alloc_len)
+{
+ BMEdge **edgenet = *r_edgenet;
+ int edgenet_alloc_len = *r_edgenet_alloc_len;
+
+ BMIter iter;
+ BMEdge *e;
+ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) {
+ int edgenet_len = 0;
+ BMVert *v_other = v;
+ while (BM_edge_is_wire(e)) {
+ if (edgenet_alloc_len == edgenet_len) {
+ edgenet_alloc_len = (edgenet_alloc_len + 1) * 2;
+ edgenet = MEM_reallocN(edgenet, (edgenet_alloc_len) * sizeof(*edgenet));
+ }
+ edgenet[edgenet_len++] = e;
+ v_other = BM_edge_other_vert(e, v_other);
+ if (v_other == v) {
+ /* Endless loop. */
+ break;
+ }
+
+ BMEdge *e_next = BM_DISK_EDGE_NEXT(e, v_other);
+ if (e_next == e) {
+ /* Vert is wire_endpoint */
+ edgenet_len = 0;
+ break;
+ }
+ e = e_next;
+ }
+
+ BMLoop *dummy;
+ BMFace *best_face;
+ if (edgenet_len == 0) {
+ /* Nothing to do. */
+ continue;
+ }
+ if (edgenet_len == 1) {
+ float data[2][3];
+ copy_v3_v3(data[0], v_other->co);
+ sub_v3_v3v3(data[1], v->co, data[0]);
+ best_face = BM_vert_pair_shared_face_cb(
+ v_other, v, true, edbm_vert_pair_share_splittable_face_cb, &data, &dummy, &dummy);
+ }
+ else {
+ struct EDBMSplitBestFaceData data = {
+ .edgenet = edgenet,
+ .edgenet_len = edgenet_len,
+ .best_face_range_on_normal_axis = FLT_MAX,
+ .r_best_face = NULL,
+ };
+ BM_vert_pair_shared_face_cb(
+ v_other, v, true, edbm_vert_pair_share_best_splittable_face_cb, &data, &dummy, &dummy);
+
+ best_face = data.r_best_face;
+ }
+
+ if (best_face) {
+ BM_face_split_edgenet(bm, best_face, edgenet, edgenet_len, NULL, NULL);
+ }
+ }
+
+ *r_edgenet = edgenet;
+ *r_edgenet_alloc_len = edgenet_alloc_len;
+}
+
+static void ebbm_automerge_and_split_find_duplicate_cb(void *userdata,
+ int index,
+ const float co[3],
+ BVHTreeNearest *nearest)
+{
+ struct EDBMSplitEdgeData *data = userdata;
+ BMEdge *e = BM_edge_at_index(data->bm, index);
+ float lambda = line_point_factor_v3_ex(co, e->v1->co, e->v2->co, 0.0f, -1.0f);
+ if (IN_RANGE(lambda, 0.0f, 1.0f)) {
+ float near_co[3];
+ interp_v3_v3v3(near_co, e->v1->co, e->v2->co, lambda);
+ float dist_sq = len_squared_v3v3(near_co, co);
+ if (dist_sq < nearest->dist_sq) {
+ nearest->dist_sq = dist_sq;
+ nearest->index = index;
+
+ data->r_edge = e;
+ data->r_lambda = lambda;
+ }
+ }
+}
+
+static int edbm_automerge_and_split_sort_cmp_by_keys_cb(const void *index1_v,
+ const void *index2_v,
+ void *keys_v)
+{
+ const struct EDBMSplitEdge *cuts = keys_v;
+ const int *index1 = (int *)index1_v;
+ const int *index2 = (int *)index2_v;
+
+ if (cuts[*index1].lambda > cuts[*index2].lambda) {
+ return 1;
+ }
+ else {
+ return -1;
+ }
+}
+
+void EDBM_automerge_and_split(Object *obedit,
+ bool split_edges,
+ bool split_faces,
+ bool update,
+ const char hflag,
+ const float dist)
+{
+ bool ok = false;
+
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ BMesh *bm = em->bm;
+ BMOperator findop, weldop;
+ BMOpSlot *slot_targetmap;
+ BMIter iter;
+ BMVert *v;
+
+ /* tag and count the verts to be tested. */
+ BM_mesh_elem_toolflags_ensure(bm);
+ int verts_len = 0;
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, hflag)) {
+ BM_elem_flag_enable(v, BM_ELEM_TAG);
+ BMO_vert_flag_enable(bm, v, BMO_ELE_TAG);
+ verts_len++;
+ }
+ else {
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+ }
+ }
+
+ /* Search for doubles among all vertices, but only merge non-BMO_ELE_TAG
+ * vertices into BMO_ELE_TAG vertices. */
+ BMO_op_initf(bm, &findop, 0, "find_doubles verts=%av keep_verts=%Fv dist=%f", BMO_ELE_TAG, dist);
+ BMO_op_exec(bm, &findop);
+
+ /* Init weld_verts operator to later fill the targetmap. */
+ BMO_op_init(bm, &weldop, 0, "weld_verts");
+ BMO_slot_copy(&findop, slots_out, "targetmap.out", &weldop, slots_in, "targetmap");
+
+ slot_targetmap = BMO_slot_get(weldop.slots_in, "targetmap");
+
+ /* Remove duplicate vertices from the split edge test and check and split faces. */
+ GHashIterator gh_iter;
+ GHash *ghash_targetmap = BMO_SLOT_AS_GHASH(slot_targetmap);
+ GHASH_ITER (gh_iter, ghash_targetmap) {
+ v = BLI_ghashIterator_getKey(&gh_iter);
+ BMVert *v_dst = BLI_ghashIterator_getValue(&gh_iter);
+ if (!BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ /* Should this happen? */
+ SWAP(BMVert *, v, v_dst);
+ }
+ BLI_assert(BM_elem_flag_test(v, BM_ELEM_TAG));
+ BM_elem_flag_disable(v, BM_ELEM_TAG);
+
+ ok = true;
+ verts_len--;
+ }
+
+ int totedge = bm->totedge;
+ if (totedge == 0 || verts_len == 0) {
+ split_edges = false;
+ }
+
+ if (split_edges) {
+ /* Count and tag edges. */
+ BMEdge *e;
+ int edges_len = 0;
+ BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN) && !BM_elem_flag_test(e->v1, BM_ELEM_TAG) &&
+ !BM_elem_flag_test(e->v2, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ edges_len++;
+ }
+ else {
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+ }
+ }
+
+ if (edges_len) {
+ /* Use `e->head.index` to count intersections. */
+ bm->elem_index_dirty &= ~BM_EDGE;
+
+ /* Create a BVHTree of edges with `dist` as epsilon. */
+ BVHTree *tree_edges = BLI_bvhtree_new(edges_len, dist, 2, 6);
+ int i;
+ BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) {
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ float co[2][3];
+ copy_v3_v3(co[0], e->v1->co);
+ copy_v3_v3(co[1], e->v2->co);
+
+ BLI_bvhtree_insert(tree_edges, i, co[0], 2);
+
+ e->head.index = 0;
+ }
+ }
+ BLI_bvhtree_balance(tree_edges);
+
+ struct EDBMSplitEdge *cuts_iter, *cuts;
+
+ /* Store all intersections in this array. */
+ cuts = MEM_mallocN(verts_len * sizeof(*cuts), __func__);
+ cuts_iter = &cuts[0];
+
+ int cuts_len = 0;
+ int cut_edges_len = 0;
+ float dist_sq = SQUARE(dist);
+ struct EDBMSplitEdgeData data = {bm};
+
+ /* Start the search for intersections. */
+ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_TAG)) {
+ float co[3];
+ copy_v3_v3(co, v->co);
+ int e_index = BLI_bvhtree_find_nearest_first(
+ tree_edges, co, dist_sq, ebbm_automerge_and_split_find_duplicate_cb, &data);
+
+ if (e_index != -1) {
+ e = data.r_edge;
+ e->head.index++;
+
+ cuts_iter->v = v;
+ cuts_iter->e = e;
+ cuts_iter->lambda = data.r_lambda;
+ cuts_iter++;
+ cuts_len++;
+
+ if (BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_elem_flag_disable(e, BM_ELEM_TAG);
+ cut_edges_len++;
+ }
+ }
+ }
+ }
+ BLI_bvhtree_free(tree_edges);
+
+ if (cuts_len) {
+ /* Map intersections per edge. */
+ union {
+ struct {
+ int cuts_len;
+ int cuts_index[];
+ };
+ int as_int[0];
+ } * e_map_iter, *e_map;
+
+ e_map = MEM_mallocN((cut_edges_len * sizeof(*e_map)) +
+ (cuts_len * sizeof(*(e_map->cuts_index))),
+ __func__);
+
+ int map_len = 0;
+ cuts_iter = &cuts[0];
+ for (i = 0; i < cuts_len; i++, cuts_iter++) {
+ e = cuts_iter->e;
+ if (!BM_elem_flag_test(e, BM_ELEM_TAG)) {
+ BM_elem_flag_enable(e, BM_ELEM_TAG);
+ int e_cuts_len = e->head.index;
+
+ e_map_iter = (void *)&e_map->as_int[map_len];
+ e_map_iter->cuts_len = e_cuts_len;
+ e_map_iter->cuts_index[0] = i;
+
+ /* Use `e->head.index` to indicate which slot to fill with the `cuts` index. */
+ e->head.index = map_len + 1;
+ map_len += 1 + e_cuts_len;
+ }
+ else {
+ e_map->as_int[++e->head.index] = i;
+ }
+ }
+
+ /* Split Edges and Faces. */
+ for (i = 0; i < map_len;
+ e_map_iter = (void *)&e_map->as_int[i], i += 1 + e_map_iter->cuts_len) {
+
+ /* sort by lambda. */
+ BLI_qsort_r(e_map_iter->cuts_index,
+ e_map_iter->cuts_len,
+ sizeof(*(e_map->cuts_index)),
+ edbm_automerge_and_split_sort_cmp_by_keys_cb,
+ cuts);
+
+ float lambda, lambda_prev = 0.0f;
+ for (int j = 0; j < e_map_iter->cuts_len; j++) {
+ cuts_iter = &cuts[e_map_iter->cuts_index[j]];
+ lambda = (cuts_iter->lambda - lambda_prev) / (1.0f - lambda_prev);
+ lambda_prev = cuts_iter->lambda;
+ v = cuts_iter->v;
+ e = cuts_iter->e;
+
+ BMVert *v_new = BM_edge_split(bm, e, e->v1, NULL, lambda);
+
+ BMO_slot_map_elem_insert(&weldop, slot_targetmap, v_new, v);
+ }
+ }
+
+ ok = true;
+ MEM_freeN(e_map);
+ }
+
+ MEM_freeN(cuts);
+ }
+ }
+
+ BMO_op_exec(bm, &weldop);
+
+ BMEdge **edgenet = NULL;
+ int edgenet_alloc_len = 0;
+ if (split_faces) {
+ GHASH_ITER (gh_iter, ghash_targetmap) {
+ v = BLI_ghashIterator_getValue(&gh_iter);
+ BLI_assert(BM_elem_flag_test(v, hflag) || hflag == BM_ELEM_TAG);
+ edbm_automerge_weld_linked_wire_edges_into_linked_faces(bm, v, &edgenet, &edgenet_alloc_len);
+ }
+ }
+
+ if (edgenet) {
+ MEM_freeN(edgenet);
+ }
+
+ BMO_op_finish(bm, &findop);
+ BMO_op_finish(bm, &weldop);
+
+ if (LIKELY(ok) && update) {
+ EDBM_update_generic(em, true, true);
+ }
+}
+
+/** \} */
diff --git a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
index 74700e59e99..7155348fed5 100644
--- a/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
+++ b/source/blender/editors/mesh/editmesh_extrude_spin_gizmo.c
@@ -1008,8 +1008,17 @@ static void gizmo_mesh_spin_redo_setup(const bContext *C, wmGizmoGroup *gzgroup)
});
}
- /* Become modal as soon as it's started. */
- gizmo_mesh_spin_redo_modal_from_setup(C, gzgroup);
+ wmWindow *win = CTX_wm_window(C);
+ if (win && win->active) {
+ bScreen *screen = WM_window_get_active_screen(win);
+ if (screen->active_region) {
+ ARegion *ar = CTX_wm_region(C);
+ if (screen->active_region == ar) {
+ /* Become modal as soon as it's started. */
+ gizmo_mesh_spin_redo_modal_from_setup(C, gzgroup);
+ }
+ }
+ }
}
static void gizmo_mesh_spin_redo_draw_prepare(const bContext *UNUSED(C), wmGizmoGroup *gzgroup)
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index bb584094580..61f9dc43c0f 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -2658,7 +2658,7 @@ static void knifetool_init_bmbvh(KnifeTool_OpData *kcd)
Object *obedit_eval = (Object *)DEG_get_evaluated_id(kcd->vc.depsgraph, &kcd->em->ob->id);
BMEditMesh *em_eval = BKE_editmesh_from_object(obedit_eval);
- kcd->cagecos = (const float(*)[3])BKE_editmesh_vertexCos_get(
+ kcd->cagecos = (const float(*)[3])BKE_editmesh_vert_coords_alloc(
kcd->vc.depsgraph, em_eval, scene_eval, NULL);
kcd->bmbvh = BKE_bmbvh_new_from_editmesh(
@@ -2949,7 +2949,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
case KNF_MODAL_ADD_CUT_CLOSED:
if (kcd->mode == MODE_DRAGGING) {
- /* shouldn't be possible with default key-layout, just incase... */
+ /* Shouldn't be possible with default key-layout, just in case. */
if (kcd->is_drag_hold) {
kcd->is_drag_hold = false;
knifetool_update_mval(kcd, kcd->curr.mval);
diff --git a/source/blender/editors/mesh/editmesh_polybuild.c b/source/blender/editors/mesh/editmesh_polybuild.c
index 088d1672cc9..21c850160dd 100644
--- a/source/blender/editors/mesh/editmesh_polybuild.c
+++ b/source/blender/editors/mesh/editmesh_polybuild.c
@@ -122,15 +122,160 @@ static bool edbm_preselect_or_active_init_viewcontext(bContext *C,
return ok;
}
+static int edbm_polybuild_transform_at_cursor_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *UNUSED(event))
+{
+ ViewContext vc;
+ Base *basact = NULL;
+ BMElem *ele_act = NULL;
+ edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
+ BMEditMesh *em = vc.em;
+ BMesh *bm = em->bm;
+
+ invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ if (!ele_act) {
+ return OPERATOR_CANCELLED;
+ }
+
+ edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
+
+ edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
+
+ if (ele_act->head.htype == BM_VERT) {
+ BM_vert_select_set(bm, (BMVert *)ele_act, true);
+ }
+ if (ele_act->head.htype == BM_EDGE) {
+ BM_edge_select_set(bm, (BMEdge *)ele_act, true);
+ }
+ if (ele_act->head.htype == BM_FACE) {
+ BM_face_select_set(bm, (BMFace *)ele_act, true);
+ }
+
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+ if (basact != NULL) {
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+ }
+ BM_select_history_store(bm, ele_act);
+ WM_event_add_mousemove(C);
+ return OPERATOR_FINISHED;
+}
+
+void MESH_OT_polybuild_transform_at_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Poly Build Transform at Cursor";
+ ot->idname = "MESH_OT_polybuild_transform_at_cursor";
+
+ /* api callbacks */
+ ot->invoke = edbm_polybuild_transform_at_cursor_invoke;
+ ot->poll = EDBM_view3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* to give to transform */
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
+}
+
+static int edbm_polybuild_delete_at_cursor_invoke(bContext *C,
+ wmOperator *op,
+ const wmEvent *UNUSED(event))
+{
+ bool changed = false;
+
+ ViewContext vc;
+ Base *basact = NULL;
+ BMElem *ele_act = NULL;
+ edbm_preselect_or_active_init_viewcontext(C, &vc, &basact, &ele_act);
+ BMEditMesh *em = vc.em;
+ BMesh *bm = em->bm;
+
+ invert_m4_m4(vc.obedit->imat, vc.obedit->obmat);
+ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d);
+
+ if (!ele_act) {
+ return OPERATOR_CANCELLED;
+ }
+
+ edbm_selectmode_ensure(vc.scene, vc.em, SCE_SELECT_VERTEX);
+
+ if (ele_act->head.htype == BM_FACE) {
+ BMFace *f_act = (BMFace *)ele_act;
+ EDBM_flag_disable_all(em, BM_ELEM_TAG);
+ BM_elem_flag_enable(f_act, BM_ELEM_TAG);
+ if (!EDBM_op_callf(em, op, "delete geom=%hf context=%i", BM_ELEM_TAG, DEL_FACES)) {
+ return OPERATOR_CANCELLED;
+ }
+ changed = true;
+ }
+ if (ele_act->head.htype == BM_VERT) {
+ BMVert *v_act = (BMVert *)ele_act;
+ if (BM_vert_is_edge_pair(v_act)) {
+ BM_edge_collapse(bm, v_act->e, v_act, true, true);
+ changed = true;
+ }
+ else {
+ EDBM_flag_disable_all(em, BM_ELEM_TAG);
+ BM_elem_flag_enable(v_act, BM_ELEM_TAG);
+
+ if (!EDBM_op_callf(em,
+ op,
+ "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b",
+ BM_ELEM_TAG,
+ false,
+ false)) {
+ return OPERATOR_CANCELLED;
+ }
+ changed = true;
+ }
+ }
+
+ if (changed) {
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+ if (basact != NULL) {
+ if (vc.view_layer->basact != basact) {
+ ED_object_base_activate(C, basact);
+ }
+ }
+ WM_event_add_mousemove(C);
+ return OPERATOR_FINISHED;
+ }
+ else {
+ return OPERATOR_CANCELLED;
+ }
+}
+
+void MESH_OT_polybuild_delete_at_cursor(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Poly Build Delete at Cursor";
+ ot->idname = "MESH_OT_polybuild_delete_at_cursor";
+
+ /* api callbacks */
+ ot->invoke = edbm_polybuild_delete_at_cursor_invoke;
+ ot->poll = EDBM_view3d_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* to give to transform */
+ Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
+}
+
/** \} */
/* -------------------------------------------------------------------- */
/** \name Face at Cursor
* \{ */
-static int edbm_polybuild_face_at_cursor_invoke(bContext *C,
- wmOperator *UNUSED(op),
- const wmEvent *event)
+static int edbm_polybuild_face_at_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
float center[3];
bool changed = false;
@@ -168,20 +313,27 @@ static int edbm_polybuild_face_at_cursor_invoke(bContext *C,
mul_m4_v3(vc.obedit->obmat, center);
ED_view3d_win_to_3d_int(vc.v3d, vc.ar, center, event->mval, center);
mul_m4_v3(vc.obedit->imat, center);
-
- BMVert *v_tri[3];
- v_tri[0] = e_act->v1;
- v_tri[1] = e_act->v2;
- v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
- if (e_act->l && e_act->l->v == v_tri[0]) {
- SWAP(BMVert *, v_tri[0], v_tri[1]);
+ if (f_reference->len == 3 && RNA_boolean_get(op->ptr, "create_quads")) {
+ const float fac = line_point_factor_v3(center, e_act->v1->co, e_act->v2->co);
+ BMVert *v_new = BM_edge_split(bm, e_act, e_act->v1, NULL, CLAMPIS(fac, 0.0f, 1.0f));
+ copy_v3_v3(v_new->co, center);
+ edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
+ BM_vert_select_set(bm, v_new, true);
+ BM_select_history_store(bm, v_new);
+ }
+ else {
+ BMVert *v_tri[3];
+ v_tri[0] = e_act->v1;
+ v_tri[1] = e_act->v2;
+ v_tri[2] = BM_vert_create(bm, center, NULL, BM_CREATE_NOP);
+ if (e_act->l && e_act->l->v == v_tri[0]) {
+ SWAP(BMVert *, v_tri[0], v_tri[1]);
+ }
+ BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true);
+ edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
+ BM_vert_select_set(bm, v_tri[2], true);
+ BM_select_history_store(bm, v_tri[2]);
}
- // BMFace *f_new =
- BM_face_create_verts(bm, v_tri, 3, f_reference, BM_CREATE_NOP, true);
-
- edbm_flag_disable_all_multi(vc.view_layer, vc.v3d, BM_ELEM_SELECT);
- BM_vert_select_set(bm, v_tri[2], true);
- BM_select_history_store(bm, v_tri[2]);
changed = true;
}
else if (ele_act->head.htype == BM_VERT) {
@@ -281,6 +433,11 @@ void MESH_OT_polybuild_face_at_cursor(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+ RNA_def_boolean(ot->srna,
+ "create_quads",
+ true,
+ "Create quads",
+ "Automatically split edges in triangles to maintain quad topology");
/* to give to transform */
Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR_DUMMY);
}
diff --git a/source/blender/editors/mesh/editmesh_preselect_elem.c b/source/blender/editors/mesh/editmesh_preselect_elem.c
index a3e684a5493..05c4da68355 100644
--- a/source/blender/editors/mesh/editmesh_preselect_elem.c
+++ b/source/blender/editors/mesh/editmesh_preselect_elem.c
@@ -75,20 +75,49 @@ struct EditMesh_PreSelElem {
float (*verts)[3];
int verts_len;
+
+ float (*preview_tris)[3][3];
+ int preview_tris_len;
+ float (*preview_lines)[2][3];
+ int preview_lines_len;
+
+ eEditMesh_PreSelPreviewAction preview_action;
};
+void EDBM_preselect_action_set(struct EditMesh_PreSelElem *psel,
+ eEditMesh_PreSelPreviewAction action)
+{
+ psel->preview_action = action;
+}
+
+eEditMesh_PreSelPreviewAction EDBM_preselect_action_get(struct EditMesh_PreSelElem *psel)
+{
+ return psel->preview_action;
+}
+
struct EditMesh_PreSelElem *EDBM_preselect_elem_create(void)
{
struct EditMesh_PreSelElem *psel = MEM_callocN(sizeof(*psel), __func__);
+ psel->preview_action = PRESELECT_ACTION_TRANSFORM;
return psel;
}
void EDBM_preselect_elem_destroy(struct EditMesh_PreSelElem *psel)
{
EDBM_preselect_elem_clear(psel);
+ EDBM_preselect_preview_clear(psel);
MEM_freeN(psel);
}
+void EDBM_preselect_preview_clear(struct EditMesh_PreSelElem *psel)
+{
+ MEM_SAFE_FREE(psel->preview_tris);
+ psel->preview_tris_len = 0;
+
+ MEM_SAFE_FREE(psel->preview_lines);
+ psel->preview_lines_len = 0;
+}
+
void EDBM_preselect_elem_clear(struct EditMesh_PreSelElem *psel)
{
MEM_SAFE_FREE(psel->edges);
@@ -112,9 +141,42 @@ void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matr
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);
+
+ immUniformColor4ub(141, 171, 186, 100);
+ if (psel->preview_action != PRESELECT_ACTION_TRANSFORM) {
+ if (psel->preview_tris_len > 0) {
+ immBegin(GPU_PRIM_TRIS, psel->preview_tris_len * 3);
+
+ for (int i = 0; i < psel->preview_tris_len; i++) {
+ immVertex3fv(pos, psel->preview_tris[i][0]);
+ immVertex3fv(pos, psel->preview_tris[i][1]);
+ immVertex3fv(pos, psel->preview_tris[i][2]);
+ }
+ immEnd();
+ }
+
+ if (psel->preview_lines_len > 0) {
+
+ immUniformColor4ub(3, 161, 252, 200);
+ GPU_line_width(2.0f);
+ immBegin(GPU_PRIM_LINES, psel->preview_lines_len * 2);
+ for (int i = 0; i < psel->preview_lines_len; i++) {
+ immVertex3fv(pos, psel->preview_lines[i][0]);
+ immVertex3fv(pos, psel->preview_lines[i][1]);
+ }
+ immEnd();
+ }
+ }
+
+ if (psel->preview_action == PRESELECT_ACTION_DELETE) {
+ immUniformColor4ub(252, 49, 10, 200);
+ }
+ else {
+ immUniformColor4ub(3, 161, 252, 200);
+ }
if (psel->edges_len > 0) {
+ GPU_line_width(3.0f);
immBegin(GPU_PRIM_LINES, psel->edges_len * 2);
for (int i = 0; i < psel->edges_len; i++) {
@@ -126,7 +188,7 @@ void EDBM_preselect_elem_draw(struct EditMesh_PreSelElem *psel, const float matr
}
if (psel->verts_len > 0) {
- GPU_point_size(3.0f);
+ GPU_point_size(4.0f);
immBegin(GPU_PRIM_POINTS, psel->verts_len);
@@ -167,6 +229,122 @@ static void view3d_preselect_mesh_elem_update_from_edge(struct EditMesh_PreSelEl
psel->edges_len = 1;
}
+static void view3d_preselect_update_preview_triangle_from_vert(struct EditMesh_PreSelElem *psel,
+ ViewContext *vc,
+ BMesh *UNUSED(bm),
+ BMVert *eed,
+ const int mval[2])
+{
+ BMVert *v_act = eed;
+ BMEdge *e_pair[2] = {NULL};
+ float center[3];
+
+ if (v_act->e != NULL) {
+ for (uint allow_wire = 0; allow_wire < 2 && (e_pair[1] == NULL); allow_wire++) {
+ int i = 0;
+ BMEdge *e_iter = v_act->e;
+ do {
+ if ((BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) &&
+ (allow_wire ? BM_edge_is_wire(e_iter) : BM_edge_is_boundary(e_iter))) {
+ if (i == 2) {
+ e_pair[0] = e_pair[1] = NULL;
+ break;
+ }
+ e_pair[i++] = e_iter;
+ }
+ } while ((e_iter = BM_DISK_EDGE_NEXT(e_iter, v_act)) != v_act->e);
+ }
+ }
+
+ if (e_pair[1] != NULL) {
+ mul_v3_m4v3(center, vc->obedit->obmat, v_act->co);
+ ED_view3d_win_to_3d_int(vc->v3d, vc->ar, center, mval, center);
+ mul_m4_v3(vc->obedit->imat, center);
+
+ psel->preview_tris = MEM_mallocN(sizeof(*psel->preview_tris) * 2, __func__);
+ psel->preview_lines = MEM_mallocN(sizeof(*psel->preview_lines) * 4, __func__);
+
+ copy_v3_v3(psel->preview_tris[0][0], e_pair[0]->v1->co);
+ copy_v3_v3(psel->preview_tris[0][1], e_pair[0]->v2->co);
+ copy_v3_v3(psel->preview_tris[0][2], center);
+
+ copy_v3_v3(psel->preview_tris[1][0], e_pair[1]->v1->co);
+ copy_v3_v3(psel->preview_tris[1][1], e_pair[1]->v2->co);
+ copy_v3_v3(psel->preview_tris[1][2], center);
+
+ copy_v3_v3(psel->preview_lines[0][0], e_pair[0]->v1->co);
+ copy_v3_v3(psel->preview_lines[0][1], e_pair[0]->v2->co);
+
+ copy_v3_v3(psel->preview_lines[1][0], e_pair[1]->v1->co);
+ copy_v3_v3(psel->preview_lines[1][1], e_pair[1]->v2->co);
+
+ copy_v3_v3(psel->preview_lines[2][0], center);
+ if (e_pair[0]->v1 == v_act) {
+ copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v2->co);
+ }
+ else {
+ copy_v3_v3(psel->preview_lines[2][1], e_pair[0]->v1->co);
+ }
+
+ copy_v3_v3(psel->preview_lines[3][0], center);
+ if (e_pair[1]->v1 == v_act) {
+ copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v2->co);
+ }
+ else {
+ copy_v3_v3(psel->preview_lines[3][1], e_pair[1]->v1->co);
+ }
+ psel->preview_tris_len = 2;
+ psel->preview_lines_len = 4;
+ }
+}
+
+static void view3d_preselect_update_preview_triangle_from_face(struct EditMesh_PreSelElem *psel,
+ ViewContext *UNUSED(vc),
+ BMesh *UNUSED(bm),
+ BMFace *efa,
+ const int UNUSED(mval[2]))
+{
+ float(*preview_lines)[2][3] = MEM_mallocN(sizeof(*psel->edges) * efa->len, __func__);
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
+ int i = 0;
+ do {
+ vcos_get_pair(&l_iter->e->v1, preview_lines[i++], NULL);
+ } while ((l_iter = l_iter->next) != l_first);
+ psel->preview_lines = preview_lines;
+ psel->preview_lines_len = efa->len;
+}
+
+static void view3d_preselect_update_preview_triangle_from_edge(struct EditMesh_PreSelElem *psel,
+ ViewContext *vc,
+ BMesh *UNUSED(bm),
+ BMEdge *eed,
+ const int mval[2])
+{
+ float center[3];
+ psel->preview_tris = MEM_mallocN(sizeof(*psel->preview_tris), __func__);
+ psel->preview_lines = MEM_mallocN(sizeof(*psel->preview_lines) * 3, __func__);
+ mid_v3_v3v3(center, eed->v1->co, eed->v2->co);
+ mul_m4_v3(vc->obedit->obmat, center);
+ ED_view3d_win_to_3d_int(vc->v3d, vc->ar, center, mval, center);
+ mul_m4_v3(vc->obedit->imat, center);
+
+ copy_v3_v3(psel->preview_tris[0][0], eed->v1->co);
+ copy_v3_v3(psel->preview_tris[0][1], eed->v2->co);
+ copy_v3_v3(psel->preview_tris[0][2], center);
+
+ copy_v3_v3(psel->preview_lines[0][0], eed->v1->co);
+ copy_v3_v3(psel->preview_lines[0][1], eed->v2->co);
+
+ copy_v3_v3(psel->preview_lines[1][0], eed->v2->co);
+ copy_v3_v3(psel->preview_lines[1][1], center);
+
+ copy_v3_v3(psel->preview_lines[2][0], center);
+ copy_v3_v3(psel->preview_lines[2][1], eed->v1->co);
+ psel->preview_tris_len = 1;
+ psel->preview_lines_len = 3;
+}
+
static void view3d_preselect_mesh_elem_update_from_face(struct EditMesh_PreSelElem *psel,
BMesh *UNUSED(bm),
BMFace *efa,
@@ -209,4 +387,28 @@ void EDBM_preselect_elem_update_from_single(struct EditMesh_PreSelElem *psel,
}
}
+void EDBM_preselect_elem_update_preview(struct EditMesh_PreSelElem *psel,
+ struct ViewContext *vc,
+ struct BMesh *bm,
+ struct BMElem *ele,
+ const int mval[2])
+{
+ EDBM_preselect_preview_clear(psel);
+
+ switch (ele->head.htype) {
+ case BM_VERT:
+ if (EDBM_preselect_action_get(psel) == PRESELECT_ACTION_CREATE) {
+ view3d_preselect_update_preview_triangle_from_vert(psel, vc, bm, (BMVert *)ele, mval);
+ }
+ break;
+ case BM_EDGE:
+ view3d_preselect_update_preview_triangle_from_edge(psel, vc, bm, (BMEdge *)ele, mval);
+ break;
+ case BM_FACE:
+ view3d_preselect_update_preview_triangle_from_face(psel, vc, bm, (BMFace *)ele, mval);
+ break;
+ default:
+ BLI_assert(0);
+ }
+}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 94ffd9a34d6..c0bd9e9f14c 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -24,7 +24,6 @@
#include "MEM_guardedalloc.h"
#include "BLI_bitmap.h"
-#include "BLI_bitmap_draw_2d.h"
#include "BLI_listbase.h"
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
@@ -35,13 +34,9 @@
#include "BKE_context.h"
#include "BKE_report.h"
-#include "BKE_paint.h"
#include "BKE_editmesh.h"
#include "BKE_layer.h"
-#include "IMB_imbuf_types.h"
-#include "IMB_imbuf.h"
-
#include "WM_api.h"
#include "WM_types.h"
@@ -67,7 +62,6 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
-#include "DRW_engine.h"
#include "DRW_select_buffer.h"
#include "mesh_intern.h" /* own include */
@@ -172,30 +166,6 @@ void EDBM_select_mirrored(
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Select Auto-Merge
- *
- * Used after transform operations.
- * \{ */
-
-void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag)
-{
- bool ok;
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
-
- ok = BMO_op_callf(em->bm,
- BMO_FLAG_DEFAULTS,
- "automerge verts=%hv dist=%f",
- hflag,
- scene->toolsettings->doublimit);
-
- if (LIKELY(ok) && update) {
- EDBM_update_generic(em, true, true);
- }
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Back-Buffer OpenGL Selection
* \{ */
@@ -1031,8 +1001,11 @@ bool EDBM_unified_findnearest(ViewContext *vc,
bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
Base **bases,
const uint bases_len,
- bool use_boundary,
- int *r_base_index,
+ bool use_boundary_vertices,
+ bool use_boundary_edges,
+ int *r_base_index_vert,
+ int *r_base_index_edge,
+ int *r_base_index_face,
struct BMVert **r_eve,
struct BMEdge **r_eed,
struct BMFace **r_efa)
@@ -1045,10 +1018,30 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
uint base_index;
BMElem *ele;
} best = {0, NULL};
+ /* Currently unused, keep since we may want to pick the best. */
+ UNUSED_VARS(best);
+
+ struct {
+ uint base_index;
+ BMElem *ele;
+ } best_vert = {0, NULL};
+
+ struct {
+ uint base_index;
+ BMElem *ele;
+ } best_edge = {0, NULL};
+
+ struct {
+ uint base_index;
+ BMElem *ele;
+ } best_face = {0, NULL};
if (ED_view3d_win_to_ray_clipped(
vc->depsgraph, vc->ar, vc->v3d, mval_fl, ray_origin, ray_direction, true)) {
float dist_sq_best = FLT_MAX;
+ float dist_sq_best_vert = FLT_MAX;
+ float dist_sq_best_edge = FLT_MAX;
+ float dist_sq_best_face = FLT_MAX;
const bool use_vert = (r_eve != NULL);
const bool use_edge = (r_eed != NULL);
@@ -1078,18 +1071,23 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
BM_mesh_elem_index_ensure(bm, BM_VERT);
}
- if (use_boundary && (use_vert || use_edge)) {
+ if ((use_boundary_vertices || use_boundary_edges) && (use_vert || use_edge)) {
BMEdge *e;
BMIter eiter;
BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
if ((BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) && (BM_edge_is_boundary(e))) {
- if (use_vert) {
+ if (use_vert && use_boundary_vertices) {
for (uint j = 0; j < 2; j++) {
BMVert *v = *((&e->v1) + j);
float point[3];
mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co);
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best_vert) {
+ dist_sq_best_vert = dist_sq_test;
+ best_vert.base_index = base_index;
+ best_vert.ele = (BMElem *)v;
+ }
if (dist_sq_test < dist_sq_best) {
dist_sq_best = dist_sq_test;
best.base_index = base_index;
@@ -1098,7 +1096,7 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
}
}
- if (use_edge) {
+ if (use_edge && use_boundary_edges) {
float point[3];
#if 0
const float dist_sq_test = dist_squared_ray_to_seg_v3(
@@ -1114,6 +1112,11 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
mul_m4_v3(obedit->obmat, point);
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best_edge) {
+ dist_sq_best_edge = dist_sq_test;
+ best_edge.base_index = base_index;
+ best_edge.ele = (BMElem *)e;
+ }
if (dist_sq_test < dist_sq_best) {
dist_sq_best = dist_sq_test;
best.base_index = base_index;
@@ -1124,46 +1127,55 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
}
}
}
- else {
- /* Non boundary case. */
- if (use_vert) {
- BMVert *v;
- BMIter viter;
- BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
- if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) {
- float point[3];
- mul_v3_m4v3(point, obedit->obmat, v->co);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, v->co);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)v;
- }
+ /* Non boundary case. */
+ if (use_vert && !use_boundary_vertices) {
+ BMVert *v;
+ BMIter viter;
+ BM_ITER_MESH (v, &viter, bm, BM_VERTS_OF_MESH) {
+ if (BM_elem_flag_test(v, BM_ELEM_HIDDEN) == false) {
+ float point[3];
+ mul_v3_m4v3(point, obedit->obmat, coords ? coords[BM_elem_index_get(v)] : v->co);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best_vert) {
+ dist_sq_best_vert = dist_sq_test;
+ best_vert.base_index = base_index;
+ best_vert.ele = (BMElem *)v;
+ }
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)v;
}
}
}
- if (use_edge) {
- BMEdge *e;
- BMIter eiter;
- BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) {
- float point[3];
- if (coords) {
- mid_v3_v3v3(
- point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
- }
- else {
- mid_v3_v3v3(point, e->v1->co, e->v2->co);
- }
- mul_m4_v3(obedit->obmat, point);
- const float dist_sq_test = dist_squared_to_ray_v3_normalized(
- ray_origin, ray_direction, point);
- if (dist_sq_test < dist_sq_best) {
- dist_sq_best = dist_sq_test;
- best.base_index = base_index;
- best.ele = (BMElem *)e;
- }
+ }
+
+ if (use_edge && !use_boundary_edges) {
+ BMEdge *e;
+ BMIter eiter;
+ BM_ITER_MESH (e, &eiter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == false) {
+ float point[3];
+ if (coords) {
+ mid_v3_v3v3(
+ point, coords[BM_elem_index_get(e->v1)], coords[BM_elem_index_get(e->v2)]);
+ }
+ else {
+ mid_v3_v3v3(point, e->v1->co, e->v2->co);
+ }
+ mul_m4_v3(obedit->obmat, point);
+ const float dist_sq_test = dist_squared_to_ray_v3_normalized(
+ ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best_edge) {
+ dist_sq_best_edge = dist_sq_test;
+ best_edge.base_index = base_index;
+ best_edge.ele = (BMElem *)e;
+ }
+ if (dist_sq_test < dist_sq_best) {
+ dist_sq_best = dist_sq_test;
+ best.base_index = base_index;
+ best.ele = (BMElem *)e;
}
}
}
@@ -1184,6 +1196,11 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
mul_m4_v3(obedit->obmat, point);
const float dist_sq_test = dist_squared_to_ray_v3_normalized(
ray_origin, ray_direction, point);
+ if (dist_sq_test < dist_sq_best_face) {
+ dist_sq_best_face = dist_sq_test;
+ best_face.base_index = base_index;
+ best_face.ele = (BMElem *)f;
+ }
if (dist_sq_test < dist_sq_best) {
dist_sq_best = dist_sq_test;
best.base_index = base_index;
@@ -1195,7 +1212,10 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
}
}
- *r_base_index = best.base_index;
+ *r_base_index_vert = best_vert.base_index;
+ *r_base_index_edge = best_edge.base_index;
+ *r_base_index_face = best_face.base_index;
+
if (r_eve) {
*r_eve = NULL;
}
@@ -1206,22 +1226,17 @@ bool EDBM_unified_findnearest_from_raycast(ViewContext *vc,
*r_efa = NULL;
}
- if (best.ele) {
- switch (best.ele->head.htype) {
- case BM_VERT:
- *r_eve = (BMVert *)best.ele;
- break;
- case BM_EDGE:
- *r_eed = (BMEdge *)best.ele;
- break;
- case BM_FACE:
- *r_efa = (BMFace *)best.ele;
- break;
- default:
- BLI_assert(0);
- }
+ if (best_vert.ele) {
+ *r_eve = (BMVert *)best_vert.ele;
+ }
+ if (best_edge.ele) {
+ *r_eed = (BMEdge *)best_edge.ele;
}
- return (best.ele != NULL);
+ if (best_face.ele) {
+ *r_efa = (BMFace *)best_face.ele;
+ }
+
+ return (best_vert.ele != NULL || best_edge.ele != NULL || best_face.ele != NULL);
}
/** \} */
diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c
index 65c058556f5..0c4db012786 100644
--- a/source/blender/editors/mesh/editmesh_tools.c
+++ b/source/blender/editors/mesh/editmesh_tools.c
@@ -437,6 +437,7 @@ void EDBM_project_snap_verts(bContext *C, Depsgraph *depsgraph, ARegion *ar, BME
},
mval,
NULL,
+ NULL,
co_proj,
NULL)) {
mul_v3_m4v3(eve->co, obedit->imat, co_proj);
@@ -3130,12 +3131,7 @@ static int edbm_remove_doubles_exec(bContext *C, wmOperator *op)
BM_mesh_elem_hflag_enable_test(em->bm, htype_select, BM_ELEM_TAG, true, true, BM_ELEM_SELECT);
if (use_unselected) {
- EDBM_op_init(em, &bmop, op, "automerge verts=%hv dist=%f", BM_ELEM_SELECT, threshold);
- BMO_op_exec(em->bm, &bmop);
-
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- continue;
- }
+ EDBM_automerge(obedit, false, BM_ELEM_SELECT, threshold);
}
else {
EDBM_op_init(em, &bmop, op, "find_doubles verts=%hv dist=%f", BM_ELEM_SELECT, threshold);
@@ -4040,7 +4036,7 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const
ma_obdata = NULL;
}
- BKE_material_clear_id(bmain, obdata, true);
+ BKE_material_clear_id(bmain, obdata);
BKE_material_resize_object(bmain, ob, 1, true);
BKE_material_resize_id(bmain, obdata, 1, true);
@@ -4051,7 +4047,7 @@ static void mesh_separate_material_assign_mat_nr(Main *bmain, Object *ob, const
id_us_plus((ID *)ma_obdata);
}
else {
- BKE_material_clear_id(bmain, obdata, true);
+ BKE_material_clear_id(bmain, obdata);
BKE_material_resize_object(bmain, ob, 0, true);
BKE_material_resize_id(bmain, obdata, 0, true);
}
@@ -5710,7 +5706,7 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot)
"use_dissolve_boundaries",
false,
"All Boundaries",
- "Dissolve all vertices inbetween face boundaries");
+ "Dissolve all vertices in between face boundaries");
RNA_def_enum_flag(ot->srna,
"delimit",
rna_enum_mesh_delimit_mode_items,
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index d7ed14184fa..522c2f32d27 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -85,7 +85,7 @@ void EDBM_redo_state_restore(BMBackup backup, BMEditMesh *em, int recalctess)
tmpbm = NULL;
if (recalctess) {
- BKE_editmesh_tessface_calc(em);
+ BKE_editmesh_looptri_calc(em);
}
}
@@ -105,7 +105,7 @@ void EDBM_redo_state_free(BMBackup *backup, BMEditMesh *em, int recalctess)
backup->bmcopy = NULL;
if (recalctess && em) {
- BKE_editmesh_tessface_calc(em);
+ BKE_editmesh_looptri_calc(em);
}
}
@@ -162,7 +162,7 @@ bool EDBM_op_finish(BMEditMesh *em, BMOperator *bmop, wmOperator *op, const bool
/* when copying, tessellation isn't to for faster copying,
* but means we need to re-tessellate here */
if (em->looptris == NULL) {
- BKE_editmesh_tessface_calc(em);
+ BKE_editmesh_looptri_calc(em);
}
if (em->ob) {
@@ -292,10 +292,6 @@ void EDBM_mesh_make(Object *ob, const int select_mode, const bool add_key_index)
Mesh *me = ob->data;
BMesh *bm;
- if (UNLIKELY(!me->mpoly && me->totface)) {
- BKE_mesh_convert_mfaces_to_mpolys(me);
- }
-
bm = BKE_mesh_to_bmesh(me,
ob,
add_key_index,
@@ -347,10 +343,6 @@ void EDBM_mesh_load(Main *bmain, Object *ob)
.calc_object_remap = true,
}));
-#ifdef USE_TESSFACE_DEFAULT
- BKE_mesh_tessface_calc(me);
-#endif
-
/* Free derived mesh. usually this would happen through depsgraph but there
* are exceptions like file save that will not cause this, and we want to
* avoid ending up with an invalid derived mesh then.
@@ -1397,15 +1389,15 @@ void EDBM_stats_update(BMEditMesh *em)
/* so many tools call these that we better make it a generic function.
*/
-void EDBM_update_generic(BMEditMesh *em, const bool do_tessface, const bool is_destructive)
+void EDBM_update_generic(BMEditMesh *em, const bool do_tessellation, const bool is_destructive)
{
Object *ob = em->ob;
/* order of calling isn't important */
DEG_id_tag_update(ob->data, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GEOM | ND_DATA, ob->data);
- if (do_tessface) {
- BKE_editmesh_tessface_calc(em);
+ if (do_tessellation) {
+ BKE_editmesh_looptri_calc(em);
}
if (is_destructive) {
diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c
index ee8de9d8ea9..569994bead1 100644
--- a/source/blender/editors/mesh/mesh_data.c
+++ b/source/blender/editors/mesh/mesh_data.c
@@ -289,18 +289,14 @@ int ED_mesh_uv_texture_add(Mesh *me, const char *name, const bool active_set, co
if (me->mloopuv && do_init) {
CustomData_add_layer_named(
&me->ldata, CD_MLOOPUV, CD_DUPLICATE, me->mloopuv, me->totloop, name);
- CustomData_add_layer_named(
- &me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface, name);
is_init = true;
}
else {
CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, name);
- CustomData_add_layer_named(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface, name);
}
if (active_set || layernum_dst == 0) {
CustomData_set_layer_active(&me->ldata, CD_MLOOPUV, layernum_dst);
- CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum_dst);
}
BKE_mesh_update_customdata_pointers(me, true);
@@ -418,16 +414,13 @@ int ED_mesh_color_add(Mesh *me, const char *name, const bool active_set, const b
if (me->mloopcol && do_init) {
CustomData_add_layer_named(
&me->ldata, CD_MLOOPCOL, CD_DUPLICATE, me->mloopcol, me->totloop, name);
- CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface, name);
}
else {
CustomData_add_layer_named(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop, name);
- CustomData_add_layer_named(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface, name);
}
if (active_set || layernum == 0) {
CustomData_set_layer_active(&me->ldata, CD_MLOOPCOL, layernum);
- CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
}
BKE_mesh_update_customdata_pointers(me, true);
@@ -885,18 +878,8 @@ void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot)
/************************** Add Geometry Layers *************************/
-void ED_mesh_update(
- Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose, bool calc_tessface)
+void ED_mesh_update(Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose)
{
- bool tessface_input = false;
-
- if (mesh->totface > 0 && mesh->totpoly == 0) {
- BKE_mesh_convert_mfaces_to_mpolys(mesh);
-
- /* would only be converting back again, don't bother */
- tessface_input = true;
- }
-
if (calc_edges_loose && mesh->totedge) {
BKE_mesh_calc_edges_loose(mesh);
}
@@ -905,15 +888,8 @@ void ED_mesh_update(
BKE_mesh_calc_edges(mesh, calc_edges, true);
}
- if (calc_tessface) {
- if (tessface_input == false) {
- BKE_mesh_tessface_calc(mesh);
- }
- }
- else {
- /* default state is not to have tessface's so make sure this is the case */
- BKE_mesh_tessface_clear(mesh);
- }
+ /* Default state is not to have tessface's so make sure this is the case. */
+ BKE_mesh_tessface_clear(mesh);
BKE_mesh_calc_normals(mesh);
@@ -988,39 +964,6 @@ static void mesh_add_edges(Mesh *mesh, int len)
mesh->totedge = totedge;
}
-static void mesh_add_tessfaces(Mesh *mesh, int len)
-{
- CustomData fdata;
- MFace *mface;
- int i, totface;
-
- if (len == 0) {
- return;
- }
-
- totface = mesh->totface + len; /* new face count */
-
- /* update customdata */
- CustomData_copy(&mesh->fdata, &fdata, CD_MASK_MESH.fmask, CD_DEFAULT, totface);
- CustomData_copy_data(&mesh->fdata, &fdata, 0, 0, mesh->totface);
-
- if (!CustomData_has_layer(&fdata, CD_MFACE)) {
- CustomData_add_layer(&fdata, CD_MFACE, CD_CALLOC, NULL, totface);
- }
-
- CustomData_free(&mesh->fdata, mesh->totface);
- mesh->fdata = fdata;
- BKE_mesh_update_customdata_pointers(mesh, true);
-
- /* set default flags */
- mface = &mesh->mface[mesh->totface];
- for (i = 0; i < len; i++, mface++) {
- mface->flag = ME_FACE_SEL;
- }
-
- mesh->totface = totface;
-}
-
static void mesh_add_loops(Mesh *mesh, int len)
{
CustomData ldata;
@@ -1109,20 +1052,6 @@ static void mesh_remove_edges(Mesh *mesh, int len)
mesh->totedge = totedge;
}
-static void mesh_remove_faces(Mesh *mesh, int len)
-{
- int totface;
-
- if (len == 0) {
- return;
- }
-
- totface = mesh->totface - len; /* new face count */
- CustomData_free_elem(&mesh->fdata, totface, len);
-
- mesh->totface = totface;
-}
-
#if 0
void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges, int faces)
{
@@ -1143,21 +1072,6 @@ void ED_mesh_geometry_add(Mesh *mesh, ReportList *reports, int verts, int edges,
}
#endif
-void ED_mesh_tessfaces_add(Mesh *mesh, ReportList *reports, int count)
-{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot add tessfaces in edit mode");
- return;
- }
-
- if (mesh->mpoly) {
- BKE_report(reports, RPT_ERROR, "Cannot add tessfaces to a mesh that already has polygons");
- return;
- }
-
- mesh_add_tessfaces(mesh, count);
-}
-
void ED_mesh_edges_add(Mesh *mesh, ReportList *reports, int count)
{
if (mesh->edit_mesh) {
@@ -1178,20 +1092,6 @@ void ED_mesh_vertices_add(Mesh *mesh, ReportList *reports, int count)
mesh_add_verts(mesh, count);
}
-void ED_mesh_faces_remove(Mesh *mesh, ReportList *reports, int count)
-{
- if (mesh->edit_mesh) {
- BKE_report(reports, RPT_ERROR, "Cannot remove faces in edit mode");
- return;
- }
- else if (count > mesh->totface) {
- BKE_report(reports, RPT_ERROR, "Cannot remove more faces than the mesh contains");
- return;
- }
-
- mesh_remove_faces(mesh, count);
-}
-
void ED_mesh_edges_remove(Mesh *mesh, ReportList *reports, int count)
{
if (mesh->edit_mesh) {
@@ -1240,26 +1140,6 @@ void ED_mesh_polys_add(Mesh *mesh, ReportList *reports, int count)
mesh_add_polys(mesh, count);
}
-void ED_mesh_calc_tessface(Mesh *mesh, bool free_mpoly)
-{
- if (mesh->edit_mesh) {
- BKE_editmesh_tessface_calc(mesh->edit_mesh);
- }
- else {
- BKE_mesh_tessface_calc(mesh);
- }
- if (free_mpoly) {
- CustomData_free(&mesh->ldata, mesh->totloop);
- CustomData_free(&mesh->pdata, mesh->totpoly);
- mesh->totloop = 0;
- mesh->totpoly = 0;
- mesh->mloop = NULL;
- mesh->mloopcol = NULL;
- mesh->mloopuv = NULL;
- mesh->mpoly = NULL;
- }
-}
-
void ED_mesh_report_mirror_ex(wmOperator *op, int totmirr, int totfail, char selectmode)
{
const char *elem_type;
diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h
index 8d585977105..3558a07c6fb 100644
--- a/source/blender/editors/mesh/mesh_intern.h
+++ b/source/blender/editors/mesh/mesh_intern.h
@@ -122,6 +122,8 @@ void MESH_GGT_spin_redo(struct wmGizmoGroupType *gzgt);
void MESH_OT_polybuild_face_at_cursor(struct wmOperatorType *ot);
void MESH_OT_polybuild_split_at_cursor(struct wmOperatorType *ot);
void MESH_OT_polybuild_dissolve_at_cursor(struct wmOperatorType *ot);
+void MESH_OT_polybuild_transform_at_cursor(struct wmOperatorType *ot);
+void MESH_OT_polybuild_delete_at_cursor(struct wmOperatorType *ot);
/* *** editmesh_inset.c *** */
void MESH_OT_inset(struct wmOperatorType *ot);
diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c
index c3387dcfc09..9b6e991a9f5 100644
--- a/source/blender/editors/mesh/mesh_ops.c
+++ b/source/blender/editors/mesh/mesh_ops.c
@@ -145,6 +145,8 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_polybuild_face_at_cursor);
WM_operatortype_append(MESH_OT_polybuild_split_at_cursor);
WM_operatortype_append(MESH_OT_polybuild_dissolve_at_cursor);
+ WM_operatortype_append(MESH_OT_polybuild_transform_at_cursor);
+ WM_operatortype_append(MESH_OT_polybuild_delete_at_cursor);
WM_operatortype_append(MESH_OT_uv_texture_add);
WM_operatortype_append(MESH_OT_uv_texture_remove);
@@ -331,6 +333,25 @@ void ED_operatormacros_mesh(void)
otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_polybuild_transform_at_cursor_move",
+ "Transform at Cursor Move",
+ "",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_polybuild_transform_at_cursor");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
+
+ ot = WM_operatortype_append_macro("MESH_OT_polybuild_extrude_at_cursor_move",
+ "Extrude at Cursor Move",
+ "",
+ OPTYPE_UNDO | OPTYPE_REGISTER);
+ WM_operatortype_macro_define(ot, "MESH_OT_polybuild_transform_at_cursor");
+ otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_edges_indiv");
+ otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate");
+ RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false);
+ RNA_boolean_set(otmacro->ptr, "mirror", false);
}
/* note mesh keymap also for other space? */
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 2490f88b5eb..aabfa78cf58 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -48,6 +48,7 @@ set(SRC
object_collection.c
object_constraint.c
object_data_transfer.c
+ object_data_transform.c
object_edit.c
object_facemap_ops.c
object_gpencil_modifier.c
diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c
index db1aa6ca37f..3d5ec3d4ed5 100644
--- a/source/blender/editors/object/object_add.c
+++ b/source/blender/editors/object/object_add.c
@@ -103,6 +103,7 @@
#include "ED_mesh.h"
#include "ED_node.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_physics.h"
#include "ED_render.h"
#include "ED_screen.h"
@@ -502,6 +503,8 @@ Object *ED_object_add_type(bContext *C,
/* TODO(sergey): Use proper flag for tagging here. */
DEG_id_tag_update(&scene->id, 0);
+ ED_outliner_select_sync_from_object_tag(C);
+
return ob;
}
@@ -2383,13 +2386,22 @@ static int convert_exec(bContext *C, wmOperator *op)
BKE_object_free_curve_cache(newob);
}
else if (target == OB_GPENCIL) {
- /* Create a new grease pencil object */
- if (gpencil_ob == NULL) {
- const float *cur = scene->cursor.location;
- ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
- gpencil_ob = ED_gpencil_add_object(C, scene, cur, local_view_bits);
+ if (ob->type != OB_CURVE) {
+ BKE_report(
+ op->reports, RPT_ERROR, "Convert Surfaces to Grease Pencil is not supported.");
+ }
+ else {
+ /* Create a new grease pencil object only if it was not created before.
+ * All curves selected are converted as strokes of the same grease pencil object.
+ * Nurbs Surface are not supported.
+ */
+ if (gpencil_ob == NULL) {
+ const float *cur = scene->cursor.location;
+ ushort local_view_bits = (v3d && v3d->localvd) ? v3d->local_view_uuid : 0;
+ gpencil_ob = ED_gpencil_add_object(C, scene, cur, local_view_bits);
+ }
+ BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, false, false, true);
}
- BKE_gpencil_convert_curve(bmain, scene, gpencil_ob, ob, gpencil_lines, use_collections);
}
}
else if (ob->type == OB_MBALL && target == OB_MESH) {
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 7343dba420f..8981221cb9c 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -493,8 +493,12 @@ static void test_constraint(
CONSTRAINT_TYPE_CLAMPTO,
CONSTRAINT_TYPE_SPLINEIK)) {
if (ct->tar) {
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the curve is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
if (ct->tar->type != OB_CURVE) {
- ct->tar = NULL;
con->flag |= CONSTRAINT_DISABLE;
}
else {
@@ -507,8 +511,12 @@ static void test_constraint(
}
else if (con->type == CONSTRAINT_TYPE_ARMATURE) {
if (ct->tar) {
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the armature is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
if (ct->tar->type != OB_ARMATURE) {
- ct->tar = NULL;
con->flag |= CONSTRAINT_DISABLE;
}
else if (!BKE_armature_find_bone_name(BKE_armature_from_object(ct->tar),
@@ -636,7 +644,7 @@ static const EnumPropertyItem constraint_owner_items[] = {
static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", rna_type);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
if (!ptr.data) {
CTX_wm_operator_poll_msg_set(C, "Context missing 'constraint'");
@@ -648,7 +656,7 @@ static bool edit_constraint_poll_generic(bContext *C, StructRNA *rna_type)
return 0;
}
- if (ID_IS_LINKED(ob) || (ptr.id.data && ID_IS_LINKED(ptr.id.data))) {
+ if (ID_IS_LINKED(ob) || (ptr.owner_id && ID_IS_LINKED(ptr.owner_id))) {
CTX_wm_operator_poll_msg_set(C, "Cannot edit library data");
return 0;
}
@@ -680,7 +688,7 @@ static void edit_constraint_properties(wmOperatorType *ot)
static int edit_constraint_invoke_properties(bContext *C, wmOperator *op)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
bConstraint *con;
ListBase *list;
@@ -1422,14 +1430,14 @@ void ED_object_constraint_dependency_tag_update(Main *bmain, Object *ob, bConstr
static bool constraint_poll(bContext *C)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- return (ptr.id.data && ptr.data);
+ return (ptr.owner_id && ptr.data);
}
static int constraint_delete_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
- Object *ob = ptr.id.data;
+ Object *ob = (Object *)ptr.owner_id;
bConstraint *con = ptr.data;
ListBase *lb = get_constraint_lb(ob, con, NULL);
diff --git a/source/blender/editors/object/object_data_transform.c b/source/blender/editors/object/object_data_transform.c
new file mode 100644
index 00000000000..ee86c79ead5
--- /dev/null
+++ b/source/blender/editors/object/object_data_transform.c
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup edobj
+ *
+ * Use to transform object origins only.
+ *
+ * This is a small API to store & apply transformations to object data,
+ * where a transformation matrix can be continually applied ontop of the original values
+ * so we don't loose precision over time.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "DNA_anim_types.h"
+#include "DNA_armature_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_collection_types.h"
+#include "DNA_lattice_types.h"
+
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_curve.h"
+#include "BKE_mball.h"
+#include "BKE_mesh.h"
+#include "BKE_armature.h"
+#include "BKE_lattice.h"
+
+#include "DEG_depsgraph.h"
+
+#include "WM_types.h"
+
+#include "ED_object.h"
+
+#include "MEM_guardedalloc.h"
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Transform Get/Apply
+ *
+ * Some object data types don't have utility functions to access their transformation data.
+ * Define these locally.
+ *
+ * \{ */
+
+/* Armature */
+
+struct ElemData_Armature {
+ float tail[3];
+ float head[3];
+ float roll;
+ float arm_tail[3];
+ float arm_head[3];
+ float arm_roll;
+ float rad_tail;
+ float rad_head;
+ float dist;
+ float xwidth;
+ float zwidth;
+};
+
+static struct ElemData_Armature *armature_coords_and_quats_get_recurse(
+ const ListBase *bone_base, struct ElemData_Armature *elem_array)
+{
+ struct ElemData_Armature *elem = elem_array;
+ for (const Bone *bone = bone_base->first; bone; bone = bone->next) {
+
+#define COPY_PTR(member) memcpy(elem->member, bone->member, sizeof(bone->member))
+#define COPY_VAL(member) memcpy(&elem->member, &bone->member, sizeof(bone->member))
+ COPY_PTR(head);
+ COPY_PTR(tail);
+ COPY_VAL(roll);
+ COPY_PTR(arm_head);
+ COPY_PTR(arm_tail);
+ COPY_VAL(arm_roll);
+ COPY_VAL(rad_tail);
+ COPY_VAL(rad_head);
+ COPY_VAL(dist);
+ COPY_VAL(xwidth);
+ COPY_VAL(zwidth);
+#undef COPY_PTR
+#undef COPY_VAL
+
+ elem = armature_coords_and_quats_get_recurse(&bone->childbase, elem + 1);
+ }
+ return elem;
+}
+
+static void armature_coords_and_quats_get(const bArmature *arm,
+ struct ElemData_Armature *elem_array)
+{
+ armature_coords_and_quats_get_recurse(&arm->bonebase, elem_array);
+}
+
+static const struct ElemData_Armature *armature_coords_and_quats_apply_with_mat4_recurse(
+ ListBase *bone_base, const struct ElemData_Armature *elem_array, const float mat[4][4])
+{
+ const struct ElemData_Armature *elem = elem_array;
+ for (Bone *bone = bone_base->first; bone; bone = bone->next) {
+
+#define COPY_PTR(member) memcpy(bone->member, elem->member, sizeof(bone->member))
+#define COPY_VAL(member) memcpy(&bone->member, &elem->member, sizeof(bone->member))
+ COPY_PTR(head);
+ COPY_PTR(tail);
+ COPY_VAL(roll);
+ COPY_PTR(arm_head);
+ COPY_PTR(arm_tail);
+ COPY_VAL(arm_roll);
+ COPY_VAL(rad_tail);
+ COPY_VAL(rad_head);
+ COPY_VAL(dist);
+ COPY_VAL(xwidth);
+ COPY_VAL(zwidth);
+#undef COPY_PTR
+#undef COPY_VAL
+
+ elem = armature_coords_and_quats_apply_with_mat4_recurse(&bone->childbase, elem + 1, mat);
+ }
+ return elem;
+}
+
+static void armature_coords_and_quats_apply_with_mat4(bArmature *arm,
+ const struct ElemData_Armature *elem_array,
+ const float mat[4][4])
+{
+ armature_coords_and_quats_apply_with_mat4_recurse(&arm->bonebase, elem_array, mat);
+ BKE_armature_transform(arm, mat, true);
+}
+
+/* MetaBall */
+
+struct ElemData_MetaBall {
+ float co[3];
+ float quat[4];
+ float exp[3];
+ float rad;
+};
+
+static void metaball_coords_and_quats_get(const MetaBall *mb, struct ElemData_MetaBall *elem_array)
+{
+ struct ElemData_MetaBall *elem = elem_array;
+ for (const MetaElem *ml = mb->elems.first; ml; ml = ml->next, elem++) {
+ copy_v3_v3(elem->co, &ml->x);
+ copy_qt_qt(elem->quat, ml->quat);
+ copy_v3_v3(elem->exp, &ml->expx);
+ elem->rad = ml->rad;
+ }
+}
+
+static void metaball_coords_and_quats_apply_with_mat4(MetaBall *mb,
+ const struct ElemData_MetaBall *elem_array,
+ const float mat[4][4])
+{
+ const struct ElemData_MetaBall *elem = elem_array;
+ for (MetaElem *ml = mb->elems.first; ml; ml = ml->next, elem++) {
+ copy_v3_v3(&ml->x, elem->co);
+ copy_qt_qt(ml->quat, elem->quat);
+ copy_v3_v3(&ml->expx, elem->exp);
+ ml->rad = elem->rad;
+ }
+ BKE_mball_transform(mb, mat, true);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Object Data Storage API
+ *
+ * Used for interactively transforming object data.
+ *
+ * Store object data transformation in an opaque struct.
+ * \{ */
+
+struct XFormObjectData {
+ ID *id;
+};
+
+struct XFormObjectData_Mesh {
+ struct XFormObjectData base;
+ float elem_array[0][3];
+};
+
+struct XFormObjectData_Lattice {
+ struct XFormObjectData base;
+ float elem_array[0][3];
+};
+
+struct XFormObjectData_Curve {
+ struct XFormObjectData base;
+ float elem_array[0][3];
+};
+
+struct XFormObjectData_Armature {
+ struct XFormObjectData base;
+ struct ElemData_Armature elem_array[0];
+};
+
+struct XFormObjectData_MetaBall {
+ struct XFormObjectData base;
+ struct ElemData_MetaBall elem_array[0];
+};
+
+struct XFormObjectData *ED_object_data_xform_create(ID *id)
+{
+ struct XFormObjectData *xod_base = NULL;
+ switch (GS(id->name)) {
+ case ID_ME: {
+ Mesh *me = (Mesh *)id;
+ const int elem_array_len = me->totvert;
+ struct XFormObjectData_Mesh *xod = MEM_mallocN(
+ sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__);
+ BKE_mesh_vert_coords_get(me, xod->elem_array);
+ xod_base = &xod->base;
+ break;
+ }
+ case ID_LT: {
+ Lattice *lt = (Lattice *)id;
+ const int elem_array_len = lt->pntsu * lt->pntsv * lt->pntsw;
+ struct XFormObjectData_Lattice *xod = MEM_mallocN(
+ sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__);
+ BKE_lattice_vert_coords_get(lt, xod->elem_array);
+ xod_base = &xod->base;
+ break;
+ }
+ case ID_CU: {
+ Curve *cu = (Curve *)id;
+ const short ob_type = BKE_curve_type_get(cu);
+ if (ob_type == OB_FONT) {
+ /* We could support translation. */
+ break;
+ }
+ const int elem_array_len = BKE_nurbList_verts_count(&cu->nurb);
+ struct XFormObjectData_Curve *xod = MEM_mallocN(
+ sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__);
+ BKE_curve_nurbs_vert_coords_get(&cu->nurb, xod->elem_array, elem_array_len);
+ xod_base = &xod->base;
+ break;
+ }
+ case ID_AR: {
+ bArmature *arm = (bArmature *)id;
+ const int elem_array_len = BKE_armature_bonelist_count(&arm->bonebase);
+ struct XFormObjectData_Armature *xod = MEM_mallocN(
+ sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__);
+ armature_coords_and_quats_get(arm, xod->elem_array);
+ xod_base = &xod->base;
+ break;
+ }
+ case ID_MB: {
+ MetaBall *mb = (MetaBall *)id;
+ const int elem_array_len = BLI_listbase_count(&mb->elems);
+ struct XFormObjectData_MetaBall *xod = MEM_mallocN(
+ sizeof(*xod) + (sizeof(*xod->elem_array) * elem_array_len), __func__);
+ metaball_coords_and_quats_get(mb, xod->elem_array);
+ xod_base = &xod->base;
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ if (xod_base) {
+ xod_base->id = id;
+ }
+ return xod_base;
+}
+
+void ED_object_data_xform_destroy(struct XFormObjectData *xod)
+{
+ MEM_freeN(xod);
+}
+
+void ED_object_data_xform_by_mat4(struct XFormObjectData *xod_base, const float mat[4][4])
+{
+ switch (GS(xod_base->id->name)) {
+ case ID_ME: {
+ Mesh *me = (Mesh *)xod_base->id;
+ struct XFormObjectData_Mesh *xod = (struct XFormObjectData_Mesh *)xod_base;
+ BKE_mesh_vert_coords_apply_with_mat4(me, xod->elem_array, mat);
+ break;
+ }
+ case ID_LT: {
+ Lattice *lt = (Lattice *)xod_base->id;
+ struct XFormObjectData_Lattice *xod = (struct XFormObjectData_Lattice *)xod_base;
+ BKE_lattice_vert_coords_apply_with_mat4(lt, xod->elem_array, mat);
+ break;
+ }
+ case ID_CU: {
+ Curve *cu = (Curve *)xod_base->id;
+ struct XFormObjectData_Curve *xod = (struct XFormObjectData_Curve *)xod_base;
+ BKE_curve_nurbs_vert_coords_apply_with_mat4(&cu->nurb, xod->elem_array, mat, true);
+ break;
+ }
+ case ID_AR: {
+ bArmature *arm = (bArmature *)xod_base->id;
+ struct XFormObjectData_Armature *xod = (struct XFormObjectData_Armature *)xod_base;
+ armature_coords_and_quats_apply_with_mat4(arm, xod->elem_array, mat);
+ break;
+ }
+ case ID_MB: {
+ MetaBall *mb = (MetaBall *)xod_base->id;
+ struct XFormObjectData_MetaBall *xod = (struct XFormObjectData_MetaBall *)xod_base;
+ metaball_coords_and_quats_apply_with_mat4(mb, xod->elem_array, mat);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+}
+
+/** \} */
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index ed40a4eb948..33c7ffefb8b 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -116,6 +116,7 @@
typedef struct MoveToCollectionData MoveToCollectionData;
static void move_to_collection_menus_items(struct uiLayout *layout,
struct MoveToCollectionData *menu);
+static ListBase selected_objects_get(bContext *C);
/* ************* XXX **************** */
static void error(const char *UNUSED(arg))
@@ -593,7 +594,7 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag
if (LIKELY(em)) {
/* order doesn't matter */
EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
+ BKE_editmesh_looptri_calc(em);
}
WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL);
@@ -1199,7 +1200,7 @@ static int shade_smooth_exec(bContext *C, wmOperator *op)
}
if (ob->type == OB_MESH) {
- BKE_mesh_smooth_flag_set(ob, !clear);
+ BKE_mesh_smooth_flag_set(ob->data, !clear);
BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@@ -1460,6 +1461,23 @@ void OBJECT_OT_mode_set_or_submode(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+static ListBase selected_objects_get(bContext *C)
+{
+ ListBase objects = {NULL};
+
+ if (CTX_wm_space_outliner(C) != NULL) {
+ ED_outliner_selected_objects_get(C, &objects);
+ }
+ else {
+ CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
+ BLI_addtail(&objects, BLI_genericNodeN(ob));
+ }
+ CTX_DATA_END;
+ }
+
+ return objects;
+}
+
static bool move_to_collection_poll(bContext *C)
{
if (CTX_wm_space_outliner(C) != NULL) {
@@ -1472,7 +1490,7 @@ static bool move_to_collection_poll(bContext *C)
return false;
}
- return ED_operator_object_active_editable(C);
+ return ED_operator_objectmode(C);
}
}
@@ -1498,15 +1516,7 @@ static int move_to_collection_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (CTX_wm_space_outliner(C) != NULL) {
- ED_outliner_selected_objects_get(C, &objects);
- }
- else {
- CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
- BLI_addtail(&objects, BLI_genericNodeN(ob));
- }
- CTX_DATA_END;
- }
+ objects = selected_objects_get(C);
if (is_new) {
char new_collection_name[MAX_NAME];
@@ -1650,6 +1660,13 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
{
Scene *scene = CTX_data_scene(C);
+ ListBase objects = selected_objects_get(C);
+ if (BLI_listbase_is_empty(&objects)) {
+ BKE_report(op->reports, RPT_ERROR, "No objects selected");
+ return OPERATOR_CANCELLED;
+ }
+ BLI_freelistN(&objects);
+
/* Reset the menus data for the current master collection, and free previously allocated data. */
move_to_collection_menus_free(&master_collection_menu);
@@ -1674,7 +1691,7 @@ static int move_to_collection_invoke(bContext *C, wmOperator *op, const wmEvent
return move_to_collection_exec(C, op);
}
- Collection *master_collection = BKE_collection_master(scene);
+ Collection *master_collection = scene->master_collection;
/* We need the data to be allocated so it's available during menu drawing.
* Technically we could use wmOperator->customdata. However there is no free callback
diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c
index 075cd5acad6..9138e65dd2f 100644
--- a/source/blender/editors/object/object_gpencil_modifier.c
+++ b/source/blender/editors/object/object_gpencil_modifier.c
@@ -390,7 +390,7 @@ void OBJECT_OT_gpencil_modifier_add(wmOperatorType *ot)
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);
+ Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
if (!ob || ID_IS_LINKED(ob)) {
return 0;
@@ -398,7 +398,7 @@ static int gpencil_edit_modifier_poll_generic(bContext *C, StructRNA *rna_type,
if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
return 0;
}
- if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) {
+ if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) {
return 0;
}
diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c
index 15c5ea40991..bcbf7ddf9a6 100644
--- a/source/blender/editors/object/object_hook.c
+++ b/source/blender/editors/object/object_hook.c
@@ -352,7 +352,7 @@ static bool object_hook_index_array(Main *bmain,
em = me->edit_mesh;
EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
+ BKE_editmesh_looptri_calc(em);
/* check selected vertices first */
if (return_editmesh_indexar(em, r_tot, r_indexar, r_cent) == 0) {
@@ -436,7 +436,7 @@ static void object_hook_from_context(
HookModifierData *hmd;
if (ptr->data) { /* if modifier context is available, use that */
- ob = ptr->id.data;
+ ob = (Object *)ptr->owner_id;
hmd = ptr->data;
}
else { /* use the provided property */
diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c
index 8818fd71190..88d01936882 100644
--- a/source/blender/editors/object/object_modifier.c
+++ b/source/blender/editors/object/object_modifier.c
@@ -52,6 +52,7 @@
#include "BKE_editmesh.h"
#include "BKE_effect.h"
#include "BKE_global.h"
+#include "BKE_gpencil_modifier.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
@@ -110,6 +111,9 @@ static void object_force_modifier_update_for_bind(Depsgraph *depsgraph, Object *
else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
BKE_displist_make_curveTypes(depsgraph, scene_eval, ob_eval, false, false);
}
+ else if (ob->type == OB_GPENCIL) {
+ BKE_gpencil_modifiers_calc(depsgraph, scene_eval, ob_eval);
+ }
}
static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph,
@@ -714,9 +718,9 @@ static int modifier_apply_obdata(
RPT_INFO,
"Applied modifier only changed CV points, not tessellated/bevel vertices");
- vertexCos = BKE_curve_nurbs_vertexCos_get(&curve_eval->nurb, &numVerts);
+ vertexCos = BKE_curve_nurbs_vert_coords_alloc(&curve_eval->nurb, &numVerts);
mti->deformVerts(md_eval, &mectx, NULL, vertexCos, numVerts);
- BK_curve_nurbs_vertexCos_apply(&curve->nurb, vertexCos);
+ BKE_curve_nurbs_vert_coords_apply(&curve->nurb, vertexCos, false);
MEM_freeN(vertexCos);
@@ -918,7 +922,7 @@ bool edit_modifier_poll_generic(bContext *C,
const bool is_editmode_allowed)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "modifier", rna_type);
- Object *ob = (ptr.id.data) ? ptr.id.data : ED_object_active_context(C);
+ Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
if (!ob || ID_IS_LINKED(ob)) {
return 0;
@@ -926,7 +930,7 @@ bool edit_modifier_poll_generic(bContext *C,
if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
return 0;
}
- if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) {
+ if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) {
return 0;
}
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index a69f4872e72..06c360ed1cd 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -149,7 +149,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op)
em = me->edit_mesh;
EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
+ BKE_editmesh_looptri_calc(em);
/* Make sure the evaluated mesh is updated.
*
@@ -1434,7 +1434,7 @@ static int make_links_scene_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- Collection *collection_to = BKE_collection_master(scene_to);
+ Collection *collection_to = scene_to->master_collection;
CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
BKE_collection_object_add(bmain, collection_to, base->object);
}
@@ -1744,7 +1744,7 @@ static Collection *single_object_users_collection(Main *bmain,
}
/* Since master collection has already be duplicated as part of scene copy,
- * we do not duplictae it here.
+ * we do not duplicate it here.
* However, this means its children need to be re-added manually here,
* otherwise their parent lists are empty (which will lead to crashes, see T63101). */
CollectionChild *child_next, *child = collection->children.first;
@@ -1771,7 +1771,7 @@ static void single_object_users(
Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_collections)
{
/* duplicate all the objects of the scene (and matching collections, if required). */
- Collection *master_collection = BKE_collection_master(scene);
+ Collection *master_collection = scene->master_collection;
single_object_users_collection(bmain, scene, master_collection, flag, copy_collections, true);
/* duplicate collections that consist entirely of duplicated objects */
@@ -2426,6 +2426,8 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
if (!ID_IS_LINKED(obact) && obact->instance_collection != NULL &&
ID_IS_LINKED(obact->instance_collection)) {
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
+
Object *obcollection = obact;
Collection *collection = obcollection->instance_collection;
@@ -2471,7 +2473,11 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS);
}
/* parent to 'collection' empty */
- if (new_ob->parent == NULL) {
+ /* Disabled for now, according to some artist this is probably not really useful anyway.
+ * And it breaks things like objects parented to bones
+ * (most likely due to missing proper setting of inverse parent matrix?)... */
+ /* Note: we might even actually want to get rid of that instanciating empty... */
+ if (0 && new_ob->parent == NULL) {
new_ob->parent = obcollection;
}
if (new_ob == (Object *)obact->id.newid) {
@@ -2499,7 +2505,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
/* Cleanup. */
BKE_main_id_clear_newpoins(bmain);
- BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, false);
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
}
/* Else, poll func ensures us that ID_IS_LINKED(obact) is true. */
else if (obact->type == OB_ARMATURE) {
@@ -2518,7 +2524,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
/* Cleanup. */
BKE_main_id_clear_newpoins(bmain);
- BKE_main_id_tag_listbase(&bmain->objects, LIB_TAG_DOIT, false);
+ BKE_main_id_tag_all(bmain, LIB_TAG_DOIT, false);
}
/* TODO: probably more cases where we want to do automated smart things in the future! */
else {
@@ -2706,7 +2712,7 @@ static int object_unlink_data_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- id = pprop.ptr.id.data;
+ id = pprop.ptr.owner_id;
if (GS(id->name) == ID_OB) {
Object *ob = (Object *)id;
diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c
index 1bcac9b4739..5f464084a9b 100644
--- a/source/blender/editors/object/object_remesh.c
+++ b/source/blender/editors/object/object_remesh.c
@@ -108,7 +108,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- Mesh *obj_mesh_copy;
+ Mesh *obj_mesh_copy = NULL;
if (mesh->flag & ME_REMESH_REPROJECT_PAINT_MASK) {
obj_mesh_copy = BKE_mesh_new_nomain_from_template(mesh, mesh->totvert, 0, 0, 0, 0);
CustomData_copy(
@@ -126,7 +126,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op)
}
if (mesh->flag & ME_REMESH_SMOOTH_NORMALS) {
- BKE_mesh_smooth_flag_set(ob, true);
+ BKE_mesh_smooth_flag_set(ob->data, true);
}
if (ob->mode == OB_MODE_SCULPT) {
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index da06707ebac..28242b986f1 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -69,6 +69,7 @@
#include "ED_armature.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_keyframing.h"
@@ -436,6 +437,8 @@ static int object_select_by_type_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
+
return OPERATOR_FINISHED;
}
@@ -717,6 +720,7 @@ static int object_select_linked_exec(bContext *C, wmOperator *op)
if (changed) {
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
return OPERATOR_FINISHED;
}
@@ -1100,6 +1104,7 @@ static int object_select_grouped_exec(bContext *C, wmOperator *op)
if (changed) {
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
return OPERATOR_FINISHED;
}
@@ -1150,6 +1155,8 @@ static int object_select_all_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
+
return OPERATOR_FINISHED;
}
else if (any_visible == false) {
@@ -1218,6 +1225,8 @@ static int object_select_same_collection_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
+
return OPERATOR_FINISHED;
}
@@ -1281,6 +1290,8 @@ static int object_select_mirror_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
+
return OPERATOR_FINISHED;
}
@@ -1369,6 +1380,9 @@ static int object_select_more_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ ED_outliner_select_sync_from_object_tag(C);
+
return OPERATOR_FINISHED;
}
else {
@@ -1399,6 +1413,9 @@ static int object_select_less_exec(bContext *C, wmOperator *UNUSED(op))
Scene *scene = CTX_data_scene(C);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ ED_outliner_select_sync_from_object_tag(C);
+
return OPERATOR_FINISHED;
}
else {
@@ -1448,6 +1465,8 @@ static int object_select_random_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ ED_outliner_select_sync_from_object_tag(C);
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c
index 457d2421253..db0c8c54186 100644
--- a/source/blender/editors/object/object_shader_fx.c
+++ b/source/blender/editors/object/object_shader_fx.c
@@ -294,7 +294,7 @@ void OBJECT_OT_shaderfx_add(wmOperatorType *ot)
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);
+ Object *ob = (ptr.owner_id) ? (Object *)ptr.owner_id : ED_object_active_context(C);
if (!ptr.data) {
CTX_wm_operator_poll_msg_set(C, "Context missing 'shaderfx'");
@@ -307,7 +307,7 @@ static bool edit_shaderfx_poll_generic(bContext *C, StructRNA *rna_type, int obt
if (obtype_flag && ((1 << ob->type) & obtype_flag) == 0) {
return 0;
}
- if (ptr.id.data && ID_IS_LINKED(ptr.id.data)) {
+ if (ptr.owner_id && ID_IS_LINKED(ptr.owner_id)) {
return 0;
}
diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c
index 975aa0f5bac..2a8b306b085 100644
--- a/source/blender/editors/object/object_transform.c
+++ b/source/blender/editors/object/object_transform.c
@@ -77,7 +77,9 @@
#include "object_intern.h"
-/*************************** Clear Transformation ****************************/
+/* -------------------------------------------------------------------- */
+/** \name Clear Transformation Utilities
+ * \{ */
/* clear location of object */
static void object_clear_loc(Object *ob, const bool clear_delta)
@@ -284,8 +286,6 @@ static void object_clear_scale(Object *ob, const bool clear_delta)
}
}
-/* --------------- */
-
/* generic exec for clear-transform operators */
static int object_clear_transform_generic_exec(bContext *C,
wmOperator *op,
@@ -329,7 +329,11 @@ static int object_clear_transform_generic_exec(bContext *C,
return OPERATOR_FINISHED;
}
-/* --------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Location Operator
+ * \{ */
static int object_location_clear_exec(bContext *C, wmOperator *op)
{
@@ -359,6 +363,12 @@ void OBJECT_OT_location_clear(wmOperatorType *ot)
"Clear delta location in addition to clearing the normal location transform");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Rotation Operator
+ * \{ */
+
static int object_rotation_clear_exec(bContext *C, wmOperator *op)
{
return object_clear_transform_generic_exec(C, op, object_clear_rot, ANIM_KS_ROTATION_ID);
@@ -387,6 +397,12 @@ void OBJECT_OT_rotation_clear(wmOperatorType *ot)
"Clear delta rotation in addition to clearing the normal rotation transform");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Scale Operator
+ * \{ */
+
static int object_scale_clear_exec(bContext *C, wmOperator *op)
{
return object_clear_transform_generic_exec(C, op, object_clear_scale, ANIM_KS_SCALING_ID);
@@ -415,7 +431,11 @@ void OBJECT_OT_scale_clear(wmOperatorType *ot)
"Clear delta scale in addition to clearing the normal scale transform");
}
-/* --------------- */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Origin Operator
+ * \{ */
static int object_origin_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -457,7 +477,11 @@ void OBJECT_OT_origin_clear(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/*************************** Apply Transformation ****************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Apply Transformation Operator
+ * \{ */
/* use this when the loc/size/rot of the parent has changed but the children
* should stay in the same place, e.g. for apply-size-rot or object center */
@@ -744,7 +768,8 @@ static int apply_objects_internal(bContext *C,
BKE_mesh_calc_normals(me);
}
else if (ob->type == OB_ARMATURE) {
- ED_armature_transform_apply(bmain, ob, mat, do_props);
+ bArmature *arm = ob->data;
+ BKE_armature_transform(arm, mat, do_props);
}
else if (ob->type == OB_LATTICE) {
Lattice *lt = ob->data;
@@ -960,7 +985,11 @@ void OBJECT_OT_transform_apply(wmOperatorType *ot)
"Modify properties such as curve vertex radius, font size and bone envelope");
}
-/********************* Set Object Center ************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Object Center Operator
+ * \{ */
enum {
GEOMETRY_TO_ORIGIN = 0,
@@ -1152,7 +1181,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
else if (ELEM(ob->type, OB_CURVE, OB_SURF)) {
Curve *cu = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) { /* done */
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
}
else if (around == V3D_AROUND_CENTER_MEDIAN) {
BKE_curve_center_median(cu, cent);
@@ -1244,7 +1274,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
else if (ob->type == OB_MBALL) {
MetaBall *mb = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) { /* done */
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
}
else if (around == V3D_AROUND_CENTER_MEDIAN) {
BKE_mball_center_median(mb, cent);
@@ -1270,7 +1301,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
else if (ob->type == OB_LATTICE) {
Lattice *lt = ob->data;
- if (centermode == ORIGIN_TO_CURSOR) { /* done */
+ if (centermode == ORIGIN_TO_CURSOR) {
+ /* done */
}
else if (around == V3D_AROUND_CENTER_MEDIAN) {
BKE_lattice_center_median(lt, cent);
@@ -1323,11 +1355,6 @@ static int object_origin_set_exec(bContext *C, wmOperator *op)
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);
@@ -1509,6 +1536,8 @@ void OBJECT_OT_origin_set(wmOperatorType *ot)
RNA_def_enum(ot->srna, "center", prop_set_bounds_types, V3D_AROUND_CENTER_MEDIAN, "Center", "");
}
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name Transform Axis Target
*
diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c
index 08fe5e818b2..ce385b12608 100644
--- a/source/blender/editors/object/object_vgroup.c
+++ b/source/blender/editors/object/object_vgroup.c
@@ -3794,7 +3794,7 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr)
const bDeformGroup *def_a = def_a_ptr;
const bDeformGroup *def_b = def_b_ptr;
- return BLI_natstrcmp(def_a->name, def_b->name);
+ return BLI_strcasecmp_natural(def_a->name, def_b->name);
}
/**
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 0999d1f3588..fbaf02b7b3f 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -186,7 +186,7 @@ static int new_particle_settings_exec(bContext *C, wmOperator *UNUSED(op))
part = BKE_particlesettings_add(bmain, "ParticleSettings");
}
- ob = ptr.id.data;
+ ob = (Object *)ptr.owner_id;
if (psys->part) {
id_us_min(&psys->part->id);
@@ -226,7 +226,7 @@ static int new_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
Main *bmain = CTX_data_main(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys = ptr.data;
- Object *ob = ptr.id.data;
+ Object *ob = (Object *)ptr.owner_id;
ParticleTarget *pt;
@@ -273,7 +273,7 @@ static int remove_particle_target_exec(bContext *C, wmOperator *UNUSED(op))
Main *bmain = CTX_data_main(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys = ptr.data;
- Object *ob = ptr.id.data;
+ Object *ob = (Object *)ptr.owner_id;
ParticleTarget *pt;
@@ -323,7 +323,7 @@ static int target_move_up_exec(bContext *C, wmOperator *UNUSED(op))
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys = ptr.data;
- Object *ob = ptr.id.data;
+ Object *ob = (Object *)ptr.owner_id;
ParticleTarget *pt;
if (!psys) {
@@ -363,7 +363,7 @@ static int target_move_down_exec(bContext *C, wmOperator *UNUSED(op))
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
ParticleSystem *psys = ptr.data;
- Object *ob = ptr.id.data;
+ Object *ob = (Object *)ptr.owner_id;
ParticleTarget *pt;
if (!psys) {
@@ -1140,6 +1140,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
/* append to the object */
BLI_addtail(&ob_to->particlesystem, psys);
+ psys_unique_name(ob_to, psys, psys->name);
/* add a particle system modifier for each system */
md = modifier_new(eModifierType_ParticleSystem);
diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h
index 9ebbba07fdf..fc2f3d21bb6 100644
--- a/source/blender/editors/physics/physics_intern.h
+++ b/source/blender/editors/physics/physics_intern.h
@@ -30,7 +30,6 @@ struct PTCacheEdit;
struct ParticleSystem;
struct PointCache;
struct Scene;
-struct ViewLayer;
struct wmOperatorType;
/* particle_edit.c */
diff --git a/source/blender/editors/physics/physics_pointcache.c b/source/blender/editors/physics/physics_pointcache.c
index bc2f1d6cef6..700a94e4f93 100644
--- a/source/blender/editors/physics/physics_pointcache.c
+++ b/source/blender/editors/physics/physics_pointcache.c
@@ -57,7 +57,7 @@ static bool ptcache_bake_all_poll(bContext *C)
static bool ptcache_poll(bContext *C)
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- return (ptr.data && ptr.id.data);
+ return (ptr.data && ptr.owner_id);
}
typedef struct PointCacheJob {
@@ -165,7 +165,7 @@ static PTCacheBaker *ptcache_baker_create(bContext *C, wmOperator *op, bool all)
if (!all) {
PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- Object *ob = ptr.id.data;
+ Object *ob = (Object *)ptr.owner_id;
PointCache *cache = ptr.data;
baker->pid = BKE_ptcache_id_find(ob, baker->scene, cache);
}
@@ -300,7 +300,7 @@ static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op))
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
PointCache *cache = ptr.data;
- Object *ob = ptr.id.data;
+ Object *ob = (Object *)ptr.owner_id;
ptcache_free_bake(cache);
@@ -312,7 +312,7 @@ static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *UNUSED(op))
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
PointCache *cache = ptr.data;
- Object *ob = ptr.id.data;
+ Object *ob = (Object *)ptr.owner_id;
cache->flag |= PTCACHE_BAKED;
@@ -372,7 +372,7 @@ static int ptcache_add_new_exec(bContext *C, wmOperator *UNUSED(op))
{
Scene *scene = CTX_data_scene(C);
PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
- Object *ob = ptr.id.data;
+ Object *ob = (Object *)ptr.owner_id;
PointCache *cache = ptr.data;
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
@@ -392,7 +392,7 @@ static int ptcache_remove_exec(bContext *C, wmOperator *UNUSED(op))
{
PointerRNA ptr = CTX_data_pointer_get_type(C, "point_cache", &RNA_PointCache);
Scene *scene = CTX_data_scene(C);
- Object *ob = ptr.id.data;
+ Object *ob = (Object *)ptr.owner_id;
PointCache *cache = ptr.data;
PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
diff --git a/source/blender/editors/render/render_intern.h b/source/blender/editors/render/render_intern.h
index 50f0b53c037..88b913b84ca 100644
--- a/source/blender/editors/render/render_intern.h
+++ b/source/blender/editors/render/render_intern.h
@@ -24,7 +24,6 @@
#ifndef __RENDER_INTERN_H__
#define __RENDER_INTERN_H__
-struct RenderEngine;
struct ScrArea;
struct bContext;
struct wmOperatorType;
diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c
index 01740c13c9d..9f13431f25a 100644
--- a/source/blender/editors/render/render_shading.c
+++ b/source/blender/editors/render/render_shading.c
@@ -1836,7 +1836,7 @@ void SCENE_OT_freestyle_stroke_material_create(wmOperatorType *ot)
static int texture_slot_move_exec(bContext *C, wmOperator *op)
{
- ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
+ ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id;
if (id) {
MTex **mtex_ar, *mtexswap;
@@ -2031,7 +2031,7 @@ static void paste_mtex_copybuf(ID *id)
static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op))
{
- ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
+ ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id;
if (id == NULL) {
/* copying empty slot */
@@ -2046,7 +2046,7 @@ static int copy_mtex_exec(bContext *C, wmOperator *UNUSED(op))
static bool copy_mtex_poll(bContext *C)
{
- ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
+ ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id;
return (id != NULL);
}
@@ -2069,7 +2069,7 @@ void TEXTURE_OT_slot_copy(wmOperatorType *ot)
static int paste_mtex_exec(bContext *C, wmOperator *UNUSED(op))
{
- ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).id.data;
+ ID *id = CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot).owner_id;
if (id == NULL) {
Material *ma = CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c
index cd5edcdc3f4..3154d5d0985 100644
--- a/source/blender/editors/render/render_view.c
+++ b/source/blender/editors/render/render_view.c
@@ -223,8 +223,8 @@ ScrArea *render_view_open(bContext *C, int mx, int my, ReportList *reports)
/* get the correct image, and scale it */
sima->image = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result");
- /* if we're rendering to full screen, set appropriate hints on image editor
- * so it can restore properly on pressing esc */
+ /* If we're rendering to full screen, set appropriate hints on image editor
+ * so it can restore properly on pressing escape. */
if (sa->full) {
sima->flag |= SI_FULLWINDOW;
diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c
index 1775a0c55a2..b0c9e3b9378 100644
--- a/source/blender/editors/screen/area.c
+++ b/source/blender/editors/screen/area.c
@@ -1052,16 +1052,11 @@ static void region_azones_scrollbars_initialize(ScrArea *sa, ARegion *ar)
}
/* *************************************************************** */
-
-static void region_azones_add(const bScreen *screen, ScrArea *sa, ARegion *ar, const int alignment)
+static void region_azones_add_edge(ScrArea *sa,
+ ARegion *ar,
+ const int alignment,
+ const bool is_fullscreen)
{
- const bool is_fullscreen = screen->state == SCREENFULL;
-
- /* Only display tab or icons when the header region is hidden
- * (not the tool header - they overlap). */
- if (ar->regiontype == RGN_TYPE_TOOL_HEADER) {
- return;
- }
/* edge code (t b l r) is along which area edge azone will be drawn */
if (alignment == RGN_ALIGN_TOP) {
@@ -1076,6 +1071,25 @@ static void region_azones_add(const bScreen *screen, ScrArea *sa, ARegion *ar, c
else if (alignment == RGN_ALIGN_LEFT) {
region_azone_edge_initialize(sa, ar, AE_RIGHT_TO_TOPLEFT, is_fullscreen);
}
+}
+
+static void region_azones_add(const bScreen *screen, ScrArea *sa, ARegion *ar)
+{
+ const bool is_fullscreen = screen->state == SCREENFULL;
+
+ /* Only display tab or icons when the header region is hidden
+ * (not the tool header - they overlap). */
+ if (ar->regiontype == RGN_TYPE_TOOL_HEADER) {
+ return;
+ }
+
+ region_azones_add_edge(sa, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->alignment), is_fullscreen);
+
+ /* For a split region also continue the azone edge from the next region if this region is aligned
+ * with the next */
+ if ((ar->alignment & RGN_SPLIT_PREV) && ar->prev) {
+ region_azones_add_edge(sa, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->prev->alignment), is_fullscreen);
+ }
if (is_fullscreen) {
fullscreen_azone_initialize(sa, ar);
@@ -1251,9 +1265,6 @@ static void region_rect_recursive(
else if (ED_area_is_global(sa)) {
prefsizey = ED_region_global_size_y();
}
- else if (ar->regiontype == RGN_TYPE_UI && sa->spacetype == SPACE_FILE) {
- prefsizey = UI_UNIT_Y * 2 + (UI_UNIT_Y / 2);
- }
else {
prefsizey = UI_DPI_FAC * (ar->sizey > 1 ? ar->sizey + 0.5f : ar->type->prefsizey);
}
@@ -1695,7 +1706,7 @@ void ED_area_update_region_sizes(wmWindowManager *wm, wmWindow *win, ScrArea *ar
}
/* Some AZones use View2D data which is only updated in region init, so call that first! */
- region_azones_add(screen, area, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->alignment));
+ region_azones_add(screen, area, ar);
}
ED_area_azones_update(area, &win->eventstate->x);
@@ -1766,7 +1777,7 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa)
}
/* Some AZones use View2D data which is only updated in region init, so call that first! */
- region_azones_add(screen, sa, ar, RGN_ALIGN_ENUM_FROM_MASK(ar->alignment));
+ region_azones_add(screen, sa, ar);
}
/* Avoid re-initializing tools while resizing the window. */
diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c
index 2eb7f732534..6f8b25f782b 100644
--- a/source/blender/editors/screen/screen_context.c
+++ b/source/blender/editors/screen/screen_context.c
@@ -533,7 +533,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult
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);
+ CTX_data_pointer_set(result, ptr.owner_id, ptr.type, ptr.data);
return 1;
}
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index dddc33e3ad0..b37aa47aba6 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -292,33 +292,45 @@ void screen_new_activate_prepare(const wmWindow *win, bScreen *screen_new)
/* used with join operator */
int area_getorientation(ScrArea *sa, ScrArea *sb)
{
- ScrVert *sav1, *sav2, *sav3, *sav4;
- ScrVert *sbv1, *sbv2, *sbv3, *sbv4;
-
if (sa == NULL || sb == NULL) {
return -1;
}
- sav1 = sa->v1;
- sav2 = sa->v2;
- sav3 = sa->v3;
- sav4 = sa->v4;
- sbv1 = sb->v1;
- sbv2 = sb->v2;
- sbv3 = sb->v3;
- sbv4 = sb->v4;
+ ScrVert *saBL = sa->v1;
+ ScrVert *saTL = sa->v2;
+ ScrVert *saTR = sa->v3;
+ ScrVert *saBR = sa->v4;
- if (sav1 == sbv4 && sav2 == sbv3) { /* sa to right of sb = W */
- return 0;
+ ScrVert *sbBL = sb->v1;
+ ScrVert *sbTL = sb->v2;
+ ScrVert *sbTR = sb->v3;
+ ScrVert *sbBR = sb->v4;
+
+ int tolerance = U.pixelsize * 4;
+
+ if (saBL->vec.x == sbBR->vec.x && saTL->vec.x == sbTR->vec.x) { /* sa to right of sb = W */
+ if ((ABS(saBL->vec.y - sbBR->vec.y) <= tolerance) &&
+ (ABS(saTL->vec.y - sbTR->vec.y) <= tolerance)) {
+ return 0;
+ }
}
- else if (sav2 == sbv1 && sav3 == sbv4) { /* sa to bottom of sb = N */
- return 1;
+ else if (saTL->vec.y == sbBL->vec.y && saTR->vec.y == sbBR->vec.y) { /* sa to bottom of sb = N */
+ if ((ABS(saTL->vec.x - sbBL->vec.x) <= tolerance) &&
+ (ABS(saTR->vec.x - sbBR->vec.x) <= tolerance)) {
+ return 1;
+ }
}
- else if (sav3 == sbv2 && sav4 == sbv1) { /* sa to left of sb = E */
- return 2;
+ else if (saTR->vec.x == sbTL->vec.x && saBR->vec.x == sbBL->vec.x) { /* sa to left of sb = E */
+ if ((ABS(saTR->vec.y - sbTL->vec.y) <= tolerance) &&
+ (ABS(saBR->vec.y - sbBL->vec.y) <= tolerance)) {
+ return 2;
+ }
}
- else if (sav1 == sbv2 && sav4 == sbv3) { /* sa on top of sb = S*/
- return 3;
+ else if (saBL->vec.y == sbTL->vec.y && saBR->vec.y == sbTR->vec.y) { /* sa on top of sb = S*/
+ if ((ABS(saBL->vec.x - sbTL->vec.x) <= tolerance) &&
+ (ABS(saBR->vec.x - sbTR->vec.x) <= tolerance)) {
+ return 3;
+ }
}
return -1;
@@ -329,36 +341,50 @@ int area_getorientation(ScrArea *sa, ScrArea *sb)
*/
int screen_area_join(bContext *C, bScreen *scr, ScrArea *sa1, ScrArea *sa2)
{
- int dir;
-
- dir = area_getorientation(sa1, sa2);
- /*printf("dir is : %i\n", dir);*/
+ int dir = area_getorientation(sa1, sa2);
if (dir == -1) {
return 0;
}
- if (dir == 0) {
- sa1->v1 = sa2->v1;
- sa1->v2 = sa2->v2;
+ /* Align areas if they are not. Do sanity checking before getting here. */
+
+ if (dir == 0 || dir == 2) {
+ /* horizontal join, so vertically align source vert to target */
+ sa2->v1->vec.y = sa1->v1->vec.y; /* vertical align sa1 BL */
+ sa2->v2->vec.y = sa1->v2->vec.y; /* vertical align sa1 TL */
+ sa2->v3->vec.y = sa1->v3->vec.y; /* vertical align sa1 TR */
+ sa2->v4->vec.y = sa1->v4->vec.y; /* vertical align sa1 BR */
+ }
+ else {
+ /* vertical join, so horizontally align source verts to target */
+ sa2->v1->vec.x = sa1->v1->vec.x; /* vertical align sa1 BL */
+ sa2->v2->vec.x = sa1->v2->vec.x; /* vertical align sa1 TL */
+ sa2->v3->vec.x = sa1->v3->vec.x; /* vertical align sa1 TR */
+ sa2->v4->vec.x = sa1->v4->vec.x; /* vertical align sa1 BR */
+ }
+
+ if (dir == 0) { /* sa1 to right of sa2 = W */
+ sa1->v1 = sa2->v1; /* BL */
+ sa1->v2 = sa2->v2; /* TL */
screen_geom_edge_add(scr, sa1->v2, sa1->v3);
screen_geom_edge_add(scr, sa1->v1, sa1->v4);
}
- else if (dir == 1) {
- sa1->v2 = sa2->v2;
- sa1->v3 = sa2->v3;
+ else if (dir == 1) { /* sa1 to bottom of sa2 = N */
+ sa1->v2 = sa2->v2; /* TL */
+ sa1->v3 = sa2->v3; /* TR */
screen_geom_edge_add(scr, sa1->v1, sa1->v2);
screen_geom_edge_add(scr, sa1->v3, sa1->v4);
}
- else if (dir == 2) {
- sa1->v3 = sa2->v3;
- sa1->v4 = sa2->v4;
+ else if (dir == 2) { /* sa1 to left of sa2 = E */
+ sa1->v3 = sa2->v3; /* TR */
+ sa1->v4 = sa2->v4; /* BR */
screen_geom_edge_add(scr, sa1->v2, sa1->v3);
screen_geom_edge_add(scr, sa1->v1, sa1->v4);
}
- else if (dir == 3) {
- sa1->v1 = sa2->v1;
- sa1->v4 = sa2->v4;
+ else if (dir == 3) { /* sa1 on top of sa2 = S */
+ sa1->v1 = sa2->v1; /* BL */
+ sa1->v4 = sa2->v4; /* BR */
screen_geom_edge_add(scr, sa1->v1, sa1->v2);
screen_geom_edge_add(scr, sa1->v3, sa1->v4);
}
@@ -1116,7 +1142,7 @@ void ED_screen_full_prevspace(bContext *C, ScrArea *sa)
void ED_screen_restore_temp_type(bContext *C, ScrArea *sa)
{
- /* incase nether functions below run */
+ /* In case nether functions below run. */
ED_area_tag_redraw(sa);
if (sa->flag & AREA_FLAG_TEMP_TYPE) {
diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c
index 8377fd0e128..50e5597ac0c 100644
--- a/source/blender/editors/screen/screen_ops.c
+++ b/source/blender/editors/screen/screen_ops.c
@@ -1121,6 +1121,47 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Area edge detection utility
+ * \{ */
+
+static ScrEdge *screen_area_edge_from_cursor(const bContext *C,
+ const int cursor[2],
+ ScrArea **r_sa1,
+ ScrArea **r_sa2)
+{
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *sc = CTX_wm_screen(C);
+ ScrEdge *actedge;
+ rcti window_rect;
+ WM_window_rect_calc(win, &window_rect);
+ actedge = screen_geom_area_map_find_active_scredge(
+ AREAMAP_FROM_SCREEN(sc), &window_rect, cursor[0], cursor[1]);
+ *r_sa1 = NULL;
+ *r_sa2 = NULL;
+ if (actedge == NULL) {
+ return NULL;
+ }
+ int borderwidth = (4 * UI_DPI_FAC);
+ ScrArea *sa1, *sa2;
+ if (screen_geom_edge_is_horizontal(actedge)) {
+ sa1 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0], cursor[1] + borderwidth);
+ sa2 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0], cursor[1] - borderwidth);
+ }
+ else {
+ sa1 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0] + borderwidth, cursor[1]);
+ sa2 = BKE_screen_find_area_xy(sc, SPACE_TYPE_ANY, cursor[0] - borderwidth, cursor[1]);
+ }
+ bool isGlobal = ((sa1 && ED_area_is_global(sa1)) || (sa2 && ED_area_is_global(sa2)));
+ if (!isGlobal) {
+ *r_sa1 = sa1;
+ *r_sa2 = sa2;
+ }
+ return actedge;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Swap Area Operator
* \{ */
@@ -1139,6 +1180,7 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot)
* callbacks:
*
* invoke() gets called on shift+lmb drag in action-zone
+ * exec() execute without any user interaction, based on properties
* call init(), add handler
*
* modal() accept modal events while doing it
@@ -1229,6 +1271,19 @@ static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
+static int area_swap_exec(bContext *C, wmOperator *op)
+{
+ ScrArea *sa1, *sa2;
+ int cursor[2];
+ RNA_int_get_array(op->ptr, "cursor", cursor);
+ screen_area_edge_from_cursor(C, cursor, &sa1, &sa2);
+ if (sa1 == NULL || sa2 == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+ ED_area_swapspace(C, sa1, sa2);
+ return OPERATOR_FINISHED;
+}
+
static void SCREEN_OT_area_swap(wmOperatorType *ot)
{
ot->name = "Swap Areas";
@@ -1237,10 +1292,15 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot)
ot->invoke = area_swap_invoke;
ot->modal = area_swap_modal;
- ot->poll = ED_operator_areaactive;
+ ot->exec = area_swap_exec;
+ ot->poll = screen_active_editable;
ot->cancel = area_swap_cancel;
ot->flag = OPTYPE_BLOCKING;
+
+ /* rna */
+ RNA_def_int_vector(
+ ot->srna, "cursor", 2, NULL, INT_MIN, INT_MAX, "Cursor", "", INT_MIN, INT_MAX);
}
/** \} */
@@ -2458,6 +2518,14 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge)
return dist;
}
+static bool is_split_edge(const int alignment, const AZEdge edge)
+{
+ return ((alignment == RGN_ALIGN_BOTTOM) && (edge == AE_TOP_TO_BOTTOMRIGHT)) ||
+ ((alignment == RGN_ALIGN_TOP) && (edge == AE_BOTTOM_TO_TOPLEFT)) ||
+ ((alignment == RGN_ALIGN_LEFT) && (edge == AE_RIGHT_TO_TOPLEFT)) ||
+ ((alignment == RGN_ALIGN_RIGHT) && (edge == AE_LEFT_TO_TOPRIGHT));
+}
+
static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
sActionzoneData *sad = event->customdata;
@@ -2476,7 +2544,16 @@ static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event
op->customdata = rmd;
rmd->az = az;
- rmd->ar = az->ar;
+ /* special case for region within region - this allows the scale of
+ * the parent region if the azone edge is not the edge splitting
+ * both regions */
+ if ((az->ar->alignment & RGN_SPLIT_PREV) && az->ar->prev &&
+ !is_split_edge(RGN_ALIGN_ENUM_FROM_MASK(az->ar->alignment), az->edge)) {
+ rmd->ar = az->ar->prev;
+ }
+ else {
+ rmd->ar = az->ar;
+ }
rmd->sa = sad->sa1;
rmd->edge = az->edge;
rmd->origx = event->x;
@@ -3163,40 +3240,19 @@ static void area_join_draw_cb(const struct wmWindow *UNUSED(win), void *userdata
/* validate selection inside screen, set variables OK */
/* return 0: init failed */
-/* XXX todo: find edge based on (x,y) and set other area? */
-static int area_join_init(bContext *C, wmOperator *op)
+static int area_join_init(bContext *C, wmOperator *op, ScrArea *sa1, ScrArea *sa2)
{
- const wmWindow *win = CTX_wm_window(C);
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *sa1, *sa2;
- sAreaJoinData *jd = NULL;
- int x1, y1;
- int x2, y2;
-
- /* required properties, make negative to get return 0 if not set by caller */
- x1 = RNA_int_get(op->ptr, "min_x");
- y1 = RNA_int_get(op->ptr, "min_y");
- x2 = RNA_int_get(op->ptr, "max_x");
- y2 = RNA_int_get(op->ptr, "max_y");
-
- sa1 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, x1, y1);
- if (sa1 == NULL) {
- sa1 = BKE_screen_area_map_find_area_xy(&win->global_areas, SPACE_TYPE_ANY, x1, y1);
- }
- sa2 = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, x2, y2);
- if (sa2 == NULL) {
- sa2 = BKE_screen_area_map_find_area_xy(&win->global_areas, SPACE_TYPE_ANY, x2, y2);
- }
- if ((sa1 && ED_area_is_global(sa1)) || (sa2 && ED_area_is_global(sa2))) {
- BKE_report(
- op->reports, RPT_ERROR, "Global areas (Top Bar, Status Bar) do not support joining");
- return 0;
+ if (sa1 == NULL || sa2 == NULL) {
+ /* Get areas from cursor location if not specified. */
+ int cursor[2];
+ RNA_int_get_array(op->ptr, "cursor", cursor);
+ screen_area_edge_from_cursor(C, cursor, &sa1, &sa2);
}
- else if (sa1 == NULL || sa2 == NULL || sa1 == sa2) {
+ if (sa1 == NULL || sa2 == NULL) {
return 0;
}
- jd = (sAreaJoinData *)MEM_callocN(sizeof(sAreaJoinData), "op_area_join");
+ sAreaJoinData *jd = MEM_callocN(sizeof(sAreaJoinData), "op_area_join");
jd->sa1 = sa1;
jd->sa2 = sa2;
@@ -3249,7 +3305,7 @@ static void area_join_exit(bContext *C, wmOperator *op)
static int area_join_exec(bContext *C, wmOperator *op)
{
- if (!area_join_init(C, op)) {
+ if (!area_join_init(C, op, NULL, NULL)) {
return OPERATOR_CANCELLED;
}
@@ -3279,16 +3335,11 @@ static int area_join_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (sad->sa1 == sad->sa2) {
return OPERATOR_PASS_THROUGH;
}
-
- /* prepare operator state vars */
- RNA_int_set(op->ptr, "min_x", sad->sa1->totrct.xmin);
- RNA_int_set(op->ptr, "min_y", sad->sa1->totrct.ymin);
- RNA_int_set(op->ptr, "max_x", sad->sa2->totrct.xmin);
- RNA_int_set(op->ptr, "max_y", sad->sa2->totrct.ymin);
- }
-
- if (!area_join_init(C, op)) {
- return OPERATOR_CANCELLED;
+ else {
+ if (!area_join_init(C, op, sad->sa1, sad->sa2)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
}
/* add temp handler */
@@ -3309,7 +3360,14 @@ static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
bScreen *sc = CTX_wm_screen(C);
wmWindow *win = CTX_wm_window(C);
- sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+ sAreaJoinData *jd;
+
+ if (op->customdata == NULL) {
+ if (!area_join_init(C, op, NULL, NULL)) {
+ return OPERATOR_CANCELLED;
+ }
+ }
+ jd = (sAreaJoinData *)op->customdata;
/* execute the events */
switch (event->type) {
@@ -3419,10 +3477,8 @@ static void SCREEN_OT_area_join(wmOperatorType *ot)
ot->flag = OPTYPE_BLOCKING | OPTYPE_INTERNAL;
/* rna */
- RNA_def_int(ot->srna, "min_x", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "min_y", -100, INT_MIN, INT_MAX, "Y 1", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "max_x", -100, INT_MIN, INT_MAX, "X 2", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "max_y", -100, INT_MIN, INT_MAX, "Y 2", "", INT_MIN, INT_MAX);
+ RNA_def_int_vector(
+ ot->srna, "cursor", 2, NULL, INT_MIN, INT_MAX, "Cursor", "", INT_MIN, INT_MAX);
}
/** \} */
@@ -3433,36 +3489,74 @@ static void SCREEN_OT_area_join(wmOperatorType *ot)
static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- const wmWindow *win = CTX_wm_window(C);
- const bScreen *sc = CTX_wm_screen(C);
uiPopupMenu *pup;
uiLayout *layout;
PointerRNA ptr;
- ScrEdge *actedge;
- rcti window_rect;
- WM_window_rect_calc(win, &window_rect);
- actedge = screen_geom_area_map_find_active_scredge(
- AREAMAP_FROM_SCREEN(sc), &window_rect, event->x, event->y);
+ ScrArea *sa1, *sa2;
- if (actedge == NULL) {
+ if (screen_area_edge_from_cursor(C, &event->x, &sa1, &sa2) == NULL) {
return OPERATOR_CANCELLED;
}
pup = UI_popup_menu_begin(C, WM_operatortype_name(op->type, op->ptr), ICON_NONE);
layout = UI_popup_menu_layout(pup);
- uiItemFullO(
- layout, "SCREEN_OT_area_split", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr);
- /* store initial mouse cursor position */
+ /* Vertical Split */
+ uiItemFullO(layout,
+ "SCREEN_OT_area_split",
+ IFACE_("Vertical Split"),
+ ICON_NONE,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &ptr);
+ /* store initial mouse cursor position. */
+ RNA_int_set_array(&ptr, "cursor", &event->x);
+ RNA_enum_set(&ptr, "direction", 'v');
+
+ /* Horizontal Split */
+ uiItemFullO(layout,
+ "SCREEN_OT_area_split",
+ IFACE_("Horizontal Split"),
+ ICON_NONE,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &ptr);
+ /* store initial mouse cursor position. */
RNA_int_set_array(&ptr, "cursor", &event->x);
+ RNA_enum_set(&ptr, "direction", 'h');
- uiItemFullO(layout, "SCREEN_OT_area_join", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr);
- /* mouse cursor on edge, '4' can fail on wide edges... */
- RNA_int_set(&ptr, "min_x", event->x + 4);
- RNA_int_set(&ptr, "min_y", event->y + 4);
- RNA_int_set(&ptr, "max_x", event->x - 4);
- RNA_int_set(&ptr, "max_y", event->y - 4);
+ if (sa1 && sa2) {
+ uiItemS(layout);
+ }
+
+ /* Join needs two very similar areas. */
+ if (sa1 && sa2 && (area_getorientation(sa1, sa2) != -1)) {
+ uiItemFullO(layout,
+ "SCREEN_OT_area_join",
+ IFACE_("Join Areas"),
+ ICON_NONE,
+ NULL,
+ WM_OP_INVOKE_DEFAULT,
+ 0,
+ &ptr);
+ RNA_int_set_array(&ptr, "cursor", &event->x);
+ }
+
+ /* Swap just needs two areas. */
+ if (sa1 && sa2) {
+ uiItemFullO(layout,
+ "SCREEN_OT_area_swap",
+ IFACE_("Swap Areas"),
+ ICON_NONE,
+ NULL,
+ WM_OP_EXEC_DEFAULT,
+ 0,
+ &ptr);
+ RNA_int_set_array(&ptr, "cursor", &event->x);
+ }
UI_popup_menu_end(C, pup);
@@ -3660,7 +3754,7 @@ static void SCREEN_OT_redo_last(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Redo Last";
- ot->description = "Display menu for last action performed";
+ ot->description = "Display parameters for last action performed";
ot->idname = "SCREEN_OT_redo_last";
/* api callbacks */
@@ -3711,7 +3805,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
/* some rules... */
if (ar->regiontype != RGN_TYPE_WINDOW) {
- BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-splitted");
+ BKE_report(op->reports, RPT_ERROR, "Only window region can be 4-split");
}
else if (ar->alignment == RGN_ALIGN_QSPLIT) {
/* Exit quad-view */
@@ -3742,7 +3836,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
rv3d->viewlock = 0;
rv3d->rflag &= ~RV3D_CLIPPING;
- /* accumulate locks, incase they're mixed */
+ /* Accumulate locks, in case they're mixed. */
for (ar_iter = sa->regionbase.first; ar_iter; ar_iter = ar_iter->next) {
if (ar_iter->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d_iter = ar_iter->regiondata;
@@ -3764,7 +3858,7 @@ static int region_quadview_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCREEN | NA_EDITED, NULL);
}
else if (ar->next) {
- BKE_report(op->reports, RPT_ERROR, "Only last region can be 4-splitted");
+ BKE_report(op->reports, RPT_ERROR, "Only last region can be 4-split");
}
else {
/* Enter quad-view */
@@ -3842,6 +3936,65 @@ static void SCREEN_OT_region_quadview(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Region Toggle Operator
+ * \{ */
+
+static int region_toggle_exec(bContext *C, wmOperator *op)
+{
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "region_type");
+ ARegion *region;
+
+ if (RNA_property_is_set(op->ptr, prop)) {
+ region = BKE_area_find_region_type(CTX_wm_area(C), RNA_property_enum_get(op->ptr, prop));
+ }
+ else {
+ region = CTX_wm_region(C);
+ }
+
+ if (region) {
+ ED_region_toggle_hidden(C, region);
+ }
+ ED_region_tag_redraw(region);
+
+ return OPERATOR_FINISHED;
+}
+
+static bool region_toggle_poll(bContext *C)
+{
+ ScrArea *area = CTX_wm_area(C);
+
+ /* don't flip anything around in topbar */
+ if (area && area->spacetype == SPACE_TOPBAR) {
+ CTX_wm_operator_poll_msg_set(C, "Toggling regions in the Top-bar is not allowed");
+ return 0;
+ }
+
+ return ED_operator_areaactive(C);
+}
+
+static void SCREEN_OT_region_toggle(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Toggle Region";
+ ot->idname = "SCREEN_OT_region_toggle";
+ ot->description = "Hide or unhide the region";
+
+ /* api callbacks */
+ ot->exec = region_toggle_exec;
+ ot->poll = region_toggle_poll;
+ ot->flag = 0;
+
+ RNA_def_enum(ot->srna,
+ "region_type",
+ rna_enum_region_type_items,
+ 0,
+ "Region Type",
+ "Type of the region to toggle");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Region Flip Operator
* \{ */
@@ -4714,7 +4867,7 @@ static void SCREEN_OT_userpref_show(struct wmOperatorType *ot)
static int drivers_editor_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
int index = -1;
uiBut *but = NULL;
@@ -4775,6 +4928,40 @@ static void SCREEN_OT_drivers_editor_show(struct wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Show Info Log Operator
+ * \{ */
+
+static int info_log_show_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ int sizex = 900 * UI_DPI_FAC;
+ int sizey = 580 * UI_DPI_FAC;
+ int shift_y = 480;
+
+ /* changes context! */
+ if (WM_window_open_temp(C, event->x, event->y + shift_y, sizex, sizey, WM_WINDOW_INFO) != NULL) {
+ return OPERATOR_FINISHED;
+ }
+ else {
+ BKE_report(op->reports, RPT_ERROR, "Failed to open window!");
+ return OPERATOR_CANCELLED;
+ }
+}
+
+static void SCREEN_OT_info_log_show(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Show Info Log";
+ ot->description = "Show info log in a separate window";
+ ot->idname = "SCREEN_OT_info_log_show";
+
+ /* api callbacks */
+ ot->invoke = info_log_show_invoke;
+ ot->poll = ED_operator_screenactive;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name New Screen Operator
* \{ */
@@ -4903,7 +5090,9 @@ static void region_blend_end(bContext *C, ARegion *ar, const bool is_running)
WM_event_remove_timer(CTX_wm_manager(C), NULL, ar->regiontimer); /* frees rgi */
ar->regiontimer = NULL;
}
-/* assumes that *ar itself is not a splitted version from previous region */
+/**
+ * \note Assumes that \a ar itself is not a split version from previous region.
+ */
void ED_region_visibility_change_update_animated(bContext *C, ScrArea *sa, ARegion *ar)
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -5231,6 +5420,7 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_area_swap);
WM_operatortype_append(SCREEN_OT_region_quadview);
WM_operatortype_append(SCREEN_OT_region_scale);
+ WM_operatortype_append(SCREEN_OT_region_toggle);
WM_operatortype_append(SCREEN_OT_region_flip);
WM_operatortype_append(SCREEN_OT_header_toggle_menus);
WM_operatortype_append(SCREEN_OT_region_context_menu);
@@ -5241,6 +5431,7 @@ void ED_operatortypes_screen(void)
WM_operatortype_append(SCREEN_OT_screenshot);
WM_operatortype_append(SCREEN_OT_userpref_show);
WM_operatortype_append(SCREEN_OT_drivers_editor_show);
+ WM_operatortype_append(SCREEN_OT_info_log_show);
WM_operatortype_append(SCREEN_OT_region_blend);
WM_operatortype_append(SCREEN_OT_space_type_set_or_cycle);
WM_operatortype_append(SCREEN_OT_space_context_cycle);
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 65e10f98753..4a552fb3744 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -45,13 +45,17 @@
#include "BKE_node.h"
#include "BKE_paint.h"
#include "BKE_colortools.h"
+#include "BKE_object.h"
#include "WM_api.h"
+#include "wm_cursors.h"
#include "IMB_imbuf_types.h"
#include "ED_view3d.h"
+#include "DEG_depsgraph.h"
+
#include "GPU_draw.h"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
@@ -602,7 +606,7 @@ static bool sculpt_get_brush_geometry(bContext *C,
/* Draw an overlay that shows what effect the brush's texture will
* have on brush strength */
-static void paint_draw_tex_overlay(UnifiedPaintSettings *ups,
+static bool paint_draw_tex_overlay(UnifiedPaintSettings *ups,
Brush *brush,
ViewContext *vc,
int x,
@@ -622,7 +626,7 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups,
if (!(mtex->tex) ||
!((mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) ||
(valid && ELEM(mtex->brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_TILED)))) {
- return;
+ return false;
}
if (load_tex(brush, vc, zoom, col, primary)) {
@@ -728,18 +732,19 @@ static void paint_draw_tex_overlay(UnifiedPaintSettings *ups,
GPU_matrix_pop();
}
}
+ return true;
}
/* Draw an overlay that shows what effect the brush's texture will
* have on brush strength */
-static void paint_draw_cursor_overlay(
+static bool paint_draw_cursor_overlay(
UnifiedPaintSettings *ups, Brush *brush, ViewContext *vc, int x, int y, float zoom)
{
rctf quad;
/* check for overlay mode */
if (!(brush->overlay_flags & BRUSH_OVERLAY_CURSOR)) {
- return;
+ return false;
}
if (load_tex_cursor(brush, vc, zoom)) {
@@ -811,9 +816,10 @@ static void paint_draw_cursor_overlay(
GPU_matrix_pop();
}
}
+ return true;
}
-static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
+static bool paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
Brush *brush,
ViewContext *vc,
int x,
@@ -824,6 +830,9 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
/* Color means that primary brush texture is colored and
* secondary is used for alpha/mask control. */
bool col = ELEM(mode, PAINT_MODE_TEXTURE_3D, PAINT_MODE_TEXTURE_2D, PAINT_MODE_VERTEX);
+
+ bool alpha_overlay_active = false;
+
eOverlayControlFlags flags = BKE_paint_get_overlay_flags();
gpuPushAttr(GPU_DEPTH_BUFFER_BIT | GPU_BLEND_BIT);
@@ -836,26 +845,28 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups,
/* Colored overlay should be drawn separately. */
if (col) {
if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY)) {
- paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, true, true);
+ alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, true, true);
}
if (!(flags & PAINT_OVERLAY_OVERRIDE_SECONDARY)) {
- paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, false);
+ alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, false);
}
if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) {
- paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
+ alpha_overlay_active = paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
}
}
else {
if (!(flags & PAINT_OVERLAY_OVERRIDE_PRIMARY) && (mode != PAINT_MODE_WEIGHT)) {
- paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true);
+ alpha_overlay_active = paint_draw_tex_overlay(ups, brush, vc, x, y, zoom, false, true);
}
if (!(flags & PAINT_OVERLAY_OVERRIDE_CURSOR)) {
- paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
+ alpha_overlay_active = paint_draw_cursor_overlay(ups, brush, vc, x, y, zoom);
}
}
GPU_matrix_pop();
gpuPopAttr();
+
+ return alpha_overlay_active;
}
BLI_INLINE void draw_tri_point(
@@ -1074,6 +1085,98 @@ static bool ommit_cursor_drawing(Paint *paint, ePaintMode mode, Brush *brush)
return true;
}
+static void cursor_draw_point_screen_space(const uint gpuattr,
+ const ARegion *ar,
+ float true_location[3],
+ float obmat[4][4])
+{
+ float translation_vertex_cursor[3], location[3];
+ copy_v3_v3(location, true_location);
+ mul_m4_v3(obmat, location);
+ ED_view3d_project(ar, location, translation_vertex_cursor);
+ imm_draw_circle_fill_3d(
+ gpuattr, translation_vertex_cursor[0], translation_vertex_cursor[1], 3, 10);
+}
+
+static void cursor_draw_tiling_preview(const uint gpuattr,
+ const ARegion *ar,
+ float true_location[3],
+ Sculpt *sd,
+ Object *ob,
+ float radius)
+{
+ BoundBox *bb = BKE_object_boundbox_get(ob);
+ float orgLoc[3], location[3];
+ int dim, tile_pass = 0;
+ int start[3];
+ int end[3];
+ int cur[3];
+ const float *bbMin = bb->vec[0];
+ const float *bbMax = bb->vec[6];
+ const float *step = sd->paint.tile_offset;
+
+ copy_v3_v3(orgLoc, true_location);
+ for (dim = 0; dim < 3; ++dim) {
+ if ((sd->paint.symmetry_flags & (PAINT_TILE_X << dim)) && step[dim] > 0) {
+ start[dim] = (bbMin[dim] - orgLoc[dim] - radius) / step[dim];
+ end[dim] = (bbMax[dim] - orgLoc[dim] + radius) / step[dim];
+ }
+ else
+ start[dim] = end[dim] = 0;
+ }
+ copy_v3_v3_int(cur, start);
+ for (cur[0] = start[0]; cur[0] <= end[0]; cur[0]++) {
+ for (cur[1] = start[1]; cur[1] <= end[1]; cur[1]++) {
+ for (cur[2] = start[2]; cur[2] <= end[2]; cur[2]++) {
+ if (!cur[0] && !cur[1] && !cur[2])
+ continue; /* skip tile at orgLoc, this was already handled before all others */
+ tile_pass++;
+ for (dim = 0; dim < 3; dim++) {
+ location[dim] = cur[dim] * step[dim] + orgLoc[dim];
+ }
+ cursor_draw_point_screen_space(gpuattr, ar, location, ob->obmat);
+ }
+ }
+ }
+}
+
+static void cursor_draw_point_with_symmetry(const uint gpuattr,
+ const ARegion *ar,
+ const float true_location[3],
+ Sculpt *sd,
+ Object *ob,
+ float radius)
+{
+ const char symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
+ float location[3], symm_rot_mat[4][4];
+
+ for (int i = 0; i <= symm; ++i) {
+ if (i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || (i != 3 && i != 5)))) {
+
+ /* Axis Symmetry */
+ flip_v3_v3(location, true_location, (char)i);
+ cursor_draw_point_screen_space(gpuattr, ar, location, ob->obmat);
+
+ /* Tiling */
+ cursor_draw_tiling_preview(gpuattr, ar, location, sd, ob, radius);
+
+ /* Radial Symmetry */
+ for (char raxis = 0; raxis < 3; raxis++) {
+ for (int r = 1; r < sd->radial_symm[raxis]; r++) {
+ float angle = 2 * M_PI * r / sd->radial_symm[(int)raxis];
+ flip_v3_v3(location, true_location, (char)i);
+ unit_m4(symm_rot_mat);
+ rotate_m4(symm_rot_mat, raxis + 'X', angle);
+ mul_m4_v3(symm_rot_mat, location);
+
+ cursor_draw_tiling_preview(gpuattr, ar, location, sd, ob, radius);
+ cursor_draw_point_screen_space(gpuattr, ar, location, ob->obmat);
+ }
+ }
+ }
+ }
+}
+
static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
{
Scene *scene = CTX_data_scene(C);
@@ -1121,7 +1224,7 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
}
/* draw overlay */
- paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
+ bool alpha_overlay_active = paint_draw_alpha_overlay(ups, brush, &vc, x, y, zoomx, mode);
/* TODO: as sculpt and other paint modes are unified, this
* special mode of drawing will go away */
@@ -1158,12 +1261,12 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
}
/* make lines pretty */
- GPU_line_width(1.0f);
+ GPU_line_width(2.0f);
GPU_blend(true); /* TODO: also set blend mode? */
GPU_line_smooth(true);
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
/* set brush color */
immUniformColor3fvAlpha(outline_col, outline_alpha);
@@ -1176,7 +1279,103 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* outer at half alpha */
immUniformColor3fvAlpha(outline_col, outline_alpha * 0.5f);
}
- imm_draw_circle_wire_2d(pos, translation[0], translation[1], final_radius, 40);
+
+ /* Only sculpt mode cursor for now */
+
+ /* Disable for PBVH_GRIDS */
+ SculptSession *ss = vc.obact->sculpt;
+ bool is_multires = ss && ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS;
+
+ if ((mode == PAINT_MODE_SCULPT) && ss && !is_multires &&
+ !(brush->falloff_shape & BRUSH_AIRBRUSH)) {
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ wmWindow *win = CTX_wm_window(C);
+
+ /* Update WM mouse cursor, disable when the 3D brush cursor is enabled */
+ if (sd->paint.brush->overlay_flags & BRUSH_OVERLAY_CURSOR) {
+ WM_cursor_set(win, CURSOR_STD);
+ }
+ else {
+ WM_cursor_set(win, CURSOR_EDIT);
+ }
+
+ if (!ups->stroke_active) {
+ SculptCursorGeometryInfo gi;
+ float mouse[2] = {x - ar->winrct.xmin, y - ar->winrct.ymin};
+ if (sculpt_cursor_geometry_info_update(C, &gi, mouse, true) && !alpha_overlay_active) {
+
+ float rds;
+ if (!BKE_brush_use_locked_size(scene, brush)) {
+ rds = paint_calc_object_space_radius(&vc, gi.location, BKE_brush_size_get(scene, brush));
+ }
+ else {
+ rds = BKE_brush_unprojected_radius_get(scene, brush);
+ }
+
+ wmViewport(&ar->winrct);
+
+ /* Draw 3D active vertex preview with symmetry*/
+ if (len_v3v3(gi.active_vertex_co, gi.location) < rds) {
+ cursor_draw_point_with_symmetry(pos, ar, gi.active_vertex_co, sd, vc.obact, rds);
+ }
+
+ /* Draw 3D brush cursor */
+ GPU_matrix_push_projection();
+ ED_view3d_draw_setup_view(CTX_wm_window(C),
+ CTX_data_depsgraph_pointer(C),
+ CTX_data_scene(C),
+ ar,
+ CTX_wm_view3d(C),
+ NULL,
+ NULL,
+ NULL);
+
+ float cursor_trans[4][4], cursor_rot[4][4];
+ float z_axis[4] = {0.0f, 0.0f, 1.0f, 0.0f};
+ float quat[4];
+
+ copy_m4_m4(cursor_trans, vc.obact->obmat);
+ translate_m4(cursor_trans, gi.location[0], gi.location[1], gi.location[2]);
+ rotation_between_vecs_to_quat(quat, z_axis, gi.normal);
+ quat_to_mat4(cursor_rot, quat);
+
+ GPU_matrix_push();
+ GPU_matrix_mul(cursor_trans);
+ GPU_matrix_mul(cursor_rot);
+ imm_draw_circle_wire_3d(pos, 0, 0, rds, 40);
+ GPU_matrix_pop();
+
+ GPU_matrix_pop_projection();
+
+ wmWindowViewport(win);
+ }
+ else {
+ /* Draw default cursor when the mouse is not over the mesh or there are no supported
+ * overlays active */
+ GPU_line_width(1.0f);
+ imm_draw_circle_wire_3d(pos, translation[0], translation[1], final_radius, 40);
+ }
+ }
+ else {
+ if (vc.obact->sculpt->cache && !vc.obact->sculpt->cache->first_time) {
+ /* Draw cursor location preview when the stroke is active using the data from StrokeCache
+ */
+ float cursor_location[3];
+ wmViewport(&ar->winrct);
+ copy_v3_v3(cursor_location, ss->cache->true_location);
+ if (ss->cache->brush->sculpt_tool == SCULPT_TOOL_GRAB) {
+ add_v3_v3(cursor_location, ss->cache->grab_delta);
+ }
+ cursor_draw_point_with_symmetry(pos, ar, cursor_location, sd, vc.obact, ss->cache->radius);
+ wmWindowViewport(win);
+ }
+ }
+ }
+ else {
+ /* Draw default cursor in unsupported modes */
+ GPU_line_width(1.0f);
+ imm_draw_circle_wire_3d(pos, translation[0], translation[1], final_radius, 40);
+ }
immUnbindProgram();
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index 342d0b6e820..397b2981ace 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -1719,9 +1719,9 @@ static float project_paint_uvpixel_mask(const ProjPaintState *ps,
normalize_v3(no);
}
else {
- /* incase the */
#if 1
- /* normalizing per pixel isn't optimal, we could cache or check ps->*/
+ /* In case the normalizing per pixel isn't optimal,
+ * we could cache or access from evaluated mesh. */
normal_tri_v3(no,
ps->mvert_eval[lt_vtri[0]].co,
ps->mvert_eval[lt_vtri[1]].co,
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index ea4814857ba..5efedf69fe4 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -33,7 +33,6 @@ struct ListBase;
struct MTex;
struct Object;
struct Paint;
-struct PaintCurve;
struct PaintStroke;
struct PointerRNA;
struct RegionView3D;
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 694dae49d30..b4b1ae3b0af 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -57,6 +57,7 @@
#include "IMB_imbuf_types.h"
#include "paint_intern.h"
+#include "sculpt_intern.h"
#include <float.h>
#include <math.h>
@@ -93,6 +94,8 @@ typedef struct PaintStroke {
int cur_sample;
float last_mouse_position[2];
+ float last_scene_space_position[3];
+ bool stroke_over_mesh;
/* space distance covered so far */
float stroke_distance;
@@ -233,6 +236,17 @@ static bool paint_tool_require_location(Brush *brush, ePaintMode mode)
return true;
}
+static bool paint_stroke_use_scene_spacing(Brush *brush, ePaintMode mode)
+{
+ switch (mode) {
+ case PAINT_MODE_SCULPT:
+ return brush->flag & BRUSH_SCENE_SPACING;
+ default:
+ break;
+ }
+ return false;
+}
+
static bool paint_tool_require_inbetween_mouse_events(Brush *brush, ePaintMode mode)
{
switch (mode) {
@@ -523,6 +537,10 @@ static void paint_brush_stroke_add_step(bContext *C,
copy_v2_v2(stroke->last_mouse_position, mouse_in);
stroke->last_pressure = pressure;
+ if (paint_stroke_use_scene_spacing(brush, mode)) {
+ sculpt_stroke_get_location(C, stroke->last_scene_space_position, stroke->last_mouse_position);
+ }
+
if (paint_stroke_use_jitter(mode, brush, stroke->stroke_mode == BRUSH_STROKE_INVERT)) {
float delta[2];
float factor = stroke->zoom_2d;
@@ -600,14 +618,32 @@ static bool paint_smooth_stroke(PaintStroke *stroke,
return true;
}
-static float paint_space_stroke_spacing(const Scene *scene,
+static float paint_space_stroke_spacing(bContext *C,
+ const Scene *scene,
PaintStroke *stroke,
float size_pressure,
float spacing_pressure)
{
- /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel
- * causing very high step sizes, hanging blender [#32381] */
- const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure);
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
+ float size_clamp = 0.0f;
+ float size = BKE_brush_size_get(scene, stroke->brush) * size_pressure;
+ if (paint_stroke_use_scene_spacing(brush, mode)) {
+ if (!BKE_brush_use_locked_size(scene, brush)) {
+ size_clamp = paint_calc_object_space_radius(
+ &stroke->vc, stroke->last_scene_space_position, size);
+ }
+ else {
+ size_clamp = BKE_brush_unprojected_radius_get(scene, brush) * size_pressure;
+ }
+ }
+ else {
+ /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel
+ * causing very high step sizes, hanging blender [#32381] */
+ size_clamp = max_ff(1.0f, size);
+ }
+
float spacing = stroke->brush->spacing;
/* apply spacing pressure */
@@ -619,7 +655,12 @@ static float paint_space_stroke_spacing(const Scene *scene,
* the fact that brush can be scaled there. */
spacing *= stroke->zoom_2d;
- return max_ff(1.0, size_clamp * spacing / 50.0f);
+ if (paint_stroke_use_scene_spacing(brush, mode)) {
+ return size_clamp * spacing / 50.0f;
+ }
+ else {
+ return max_ff(1.0, size_clamp * spacing / 50.0f);
+ }
}
static float paint_stroke_overlapped_curve(Brush *br, float x, float spacing)
@@ -677,14 +718,18 @@ static float paint_stroke_integrate_overlap(Brush *br, float factor)
}
}
-static float paint_space_stroke_spacing_variable(
- const Scene *scene, PaintStroke *stroke, float pressure, float dpressure, float length)
+static float paint_space_stroke_spacing_variable(bContext *C,
+ const Scene *scene,
+ PaintStroke *stroke,
+ float pressure,
+ float dpressure,
+ float length)
{
if (BKE_brush_use_size_pressure(scene, stroke->brush)) {
/* use pressure to modify size. set spacing so that at 100%, the circles
* are aligned nicely with no overlap. for this the spacing needs to be
* the average of the previous and next size. */
- float s = paint_space_stroke_spacing(scene, stroke, 1.0f, pressure);
+ float s = paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure);
float q = s * dpressure / (2.0f * length);
float pressure_fac = (1.0f + q) / (1.0f - q);
@@ -692,14 +737,15 @@ static float paint_space_stroke_spacing_variable(
float new_size_pressure = stroke->last_pressure * pressure_fac;
/* average spacing */
- float last_spacing = paint_space_stroke_spacing(scene, stroke, last_size_pressure, pressure);
- float new_spacing = paint_space_stroke_spacing(scene, stroke, new_size_pressure, pressure);
+ float last_spacing = paint_space_stroke_spacing(
+ C, scene, stroke, last_size_pressure, pressure);
+ float new_spacing = paint_space_stroke_spacing(C, scene, stroke, new_size_pressure, pressure);
return 0.5f * (last_spacing + new_spacing);
}
else {
/* no size pressure */
- return paint_space_stroke_spacing(scene, stroke, 1.0f, pressure);
+ return paint_space_stroke_spacing(C, scene, stroke, 1.0f, pressure);
}
}
@@ -711,29 +757,57 @@ static int paint_space_stroke(bContext *C,
float final_pressure)
{
const Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
PaintStroke *stroke = op->customdata;
UnifiedPaintSettings *ups = stroke->ups;
+ Paint *paint = BKE_paint_get_active_from_context(C);
+ ePaintMode mode = BKE_paintmode_get_active_from_context(C);
+ Brush *brush = BKE_paint_brush(paint);
int cnt = 0;
float pressure, dpressure;
float mouse[2], dmouse[2];
+ float scene_space_position[3], d_scene_space_position[3], final_scene_space_position[3];
float length;
- float no_pressure_spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
-
- sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
-
+ float no_pressure_spacing = paint_space_stroke_spacing(C, scene, stroke, 1.0f, 1.0f);
pressure = stroke->last_pressure;
dpressure = final_pressure - stroke->last_pressure;
-
+ sub_v2_v2v2(dmouse, final_mouse, stroke->last_mouse_position);
length = normalize_v2(dmouse);
+ if (paint_stroke_use_scene_spacing(brush, mode)) {
+ bool hit = sculpt_stroke_get_location(C, scene_space_position, final_mouse);
+ if (hit && stroke->stroke_over_mesh) {
+ sub_v3_v3v3(d_scene_space_position, scene_space_position, stroke->last_scene_space_position);
+ length = len_v3(d_scene_space_position);
+ stroke->stroke_over_mesh = true;
+ }
+ else {
+ length = 0.0f;
+ stroke->stroke_over_mesh = hit;
+ if (stroke->stroke_over_mesh) {
+ copy_v3_v3(stroke->last_scene_space_position, scene_space_position);
+ }
+ }
+ }
+
while (length > 0.0f) {
float spacing = paint_space_stroke_spacing_variable(
- scene, stroke, pressure, dpressure, length);
+ C, scene, stroke, pressure, dpressure, length);
if (length >= spacing) {
- mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
- mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
+ if (paint_stroke_use_scene_spacing(brush, mode)) {
+ normalize_v3(d_scene_space_position);
+ mul_v3_v3fl(final_scene_space_position, d_scene_space_position, spacing);
+ add_v3_v3v3(final_scene_space_position,
+ stroke->last_scene_space_position,
+ final_scene_space_position);
+ ED_view3d_project(ar, final_scene_space_position, mouse);
+ }
+ else {
+ mouse[0] = stroke->last_mouse_position[0] + dmouse[0] * spacing;
+ mouse[1] = stroke->last_mouse_position[1] + dmouse[1] * spacing;
+ }
pressure = stroke->last_pressure + (spacing / length) * dpressure;
ups->overlap_factor = paint_stroke_integrate_overlap(stroke->brush,
@@ -1079,7 +1153,7 @@ static bool paint_stroke_curve_end(bContext *C, wmOperator *op, PaintStroke *str
if (br->flag & BRUSH_CURVE) {
UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings;
const Scene *scene = CTX_data_scene(C);
- const float spacing = paint_space_stroke_spacing(scene, stroke, 1.0f, 1.0f);
+ const float spacing = paint_space_stroke_spacing(C, scene, stroke, 1.0f, 1.0f);
PaintCurve *pc = br->paint_curve;
PaintCurvePoint *pcp;
float length_residue = 0.0f;
@@ -1250,6 +1324,10 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
if (!stroke->stroke_started) {
stroke->last_pressure = sample_average.pressure;
copy_v2_v2(stroke->last_mouse_position, sample_average.mouse);
+ if (paint_stroke_use_scene_spacing(br, mode)) {
+ stroke->stroke_over_mesh = sculpt_stroke_get_location(
+ C, stroke->last_scene_space_position, sample_average.mouse);
+ }
stroke->stroke_started = stroke->test_start(C, op, sample_average.mouse);
BLI_assert((stroke->stroke_started & ~1) == 0); /* 0/1 */
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 440c4d42cae..5aa913ad006 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -96,7 +96,18 @@
/* Do not use these functions while working with PBVH_GRIDS data in SculptSession */
-/* TODO: why is this kept, should it be removed? */
+static float *sculpt_vertex_co_get(SculptSession *ss, int index)
+{
+ switch (BKE_pbvh_type(ss->pbvh)) {
+ case PBVH_FACES:
+ return ss->mvert[index].co;
+ case PBVH_BMESH:
+ return BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->co;
+ default:
+ return NULL;
+ }
+}
+
#if 0 /* UNUSED */
static int sculpt_active_vertex_get(SculptSession *ss)
@@ -136,18 +147,6 @@ static void sculpt_vertex_normal_get(SculptSession *ss, int index, float no[3])
}
}
-static float *sculpt_vertex_co_get(SculptSession *ss, int index)
-{
- switch (BKE_pbvh_type(ss->pbvh)) {
- case PBVH_FACES:
- return ss->mvert[index].co;
- case PBVH_BMESH:
- return BM_vert_at_index(BKE_pbvh_get_bmesh(ss->pbvh), index)->co;
- default:
- return NULL;
- }
-}
-
static void sculpt_vertex_co_set(SculptSession *ss, int index, float co[3])
{
switch (BKE_pbvh_type(ss->pbvh)) {
@@ -748,17 +747,26 @@ void ED_sculpt_redraw_planes_get(float planes[4][4], ARegion *ar, Object *ob)
void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test)
{
- RegionView3D *rv3d = ss->cache->vc->rv3d;
+ RegionView3D *rv3d = ss->cache ? ss->cache->vc->rv3d : ss->rv3d;
+
+ test->radius_squared = ss->cache ? ss->cache->radius_squared :
+ ss->cursor_radius * ss->cursor_radius;
+ if (ss->cache) {
+ copy_v3_v3(test->location, ss->cache->location);
+ test->mirror_symmetry_pass = ss->cache->mirror_symmetry_pass;
+ }
+ else {
+ copy_v3_v3(test->location, ss->cursor_location);
+ test->mirror_symmetry_pass = 0;
+ }
- test->radius_squared = ss->cache->radius_squared;
- copy_v3_v3(test->location, ss->cache->location);
test->dist = 0.0f; /* just for initialize */
/* Only for 2D projection. */
zero_v4(test->plane_view);
zero_v4(test->plane_tool);
- test->mirror_symmetry_pass = ss->cache->mirror_symmetry_pass;
+ test->mirror_symmetry_pass = ss->cache ? ss->cache->mirror_symmetry_pass : 0;
if (rv3d->rflag & RV3D_CLIPPING) {
test->clip_rv3d = rv3d;
@@ -1050,7 +1058,7 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
int private_count[2] = {0};
bool use_original = false;
- if (ss->cache->original) {
+ if (ss->cache && ss->cache->original) {
unode = sculpt_undo_push_node(data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
use_original = (unode->co || unode->bm_entry);
}
@@ -1059,6 +1067,13 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
SculptBrushTestFn sculpt_brush_test_sq_fn = sculpt_brush_test_init_with_falloff_shape(
ss, &test, data->brush->falloff_shape);
+ /* Update the test radius to sample the normal using the normal radius of the brush */
+ if (data->brush->ob_mode == OB_MODE_SCULPT) {
+ float test_radius = sqrtf(test.radius_squared);
+ test_radius *= data->brush->normal_radius_factor;
+ test.radius_squared = test_radius * test_radius;
+ }
+
/* when the mesh is edited we can't rely on original coords
* (original mesh may not even have verts in brush radius) */
if (use_original && data->has_bm_orco) {
@@ -1120,6 +1135,8 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
const float *no;
int flip_index;
+ data->any_vertex_sampled = true;
+
if (use_original) {
normal_short_to_float_v3(no_buf, no_s);
no = no_buf;
@@ -1134,7 +1151,8 @@ static void calc_area_normal_and_center_task_cb(void *__restrict userdata,
}
}
- flip_index = (dot_v3v3(ss->cache->view_normal, no) <= 0.0f);
+ flip_index = (dot_v3v3(ss->cache ? ss->cache->view_normal : ss->cursor_view_normal, no) <=
+ 0.0f);
if (area_cos) {
add_v3_v3(private_co[flip_index], co);
}
@@ -1223,7 +1241,7 @@ static void calc_area_normal(
}
/* expose 'calc_area_normal' externally. */
-void sculpt_pbvh_calc_area_normal(const Brush *brush,
+bool sculpt_pbvh_calc_area_normal(const Brush *brush,
Object *ob,
PBVHNode **nodes,
int totnode,
@@ -1249,6 +1267,7 @@ void sculpt_pbvh_calc_area_normal(const Brush *brush,
.area_cos = NULL,
.area_nos = area_nos,
.count = count,
+ .any_vertex_sampled = false,
};
BLI_mutex_init(&data.mutex);
@@ -1265,6 +1284,8 @@ void sculpt_pbvh_calc_area_normal(const Brush *brush,
break;
}
}
+
+ return data.any_vertex_sampled;
}
/* this calculates flatten center and area normal together,
@@ -1508,7 +1529,8 @@ float tex_strength(SculptSession *ss,
bool sculpt_search_sphere_cb(PBVHNode *node, void *data_v)
{
SculptSearchSphereData *data = data_v;
- float *center = data->ss->cache->location, nearest[3];
+ float *center, nearest[3];
+ center = data->ss->cache ? data->ss->cache->location : data->ss->cursor_location;
float t[3], bb_min[3], bb_max[3];
int i;
@@ -1585,12 +1607,13 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob,
SculptSession *ss = ob->sculpt;
PBVHNode **nodes = NULL;
- /* Build a list of all nodes that are potentially within the brush's area of influence */
+ /* Build a list of all nodes that are potentially within the cursor or brush's area of influence
+ */
if (brush->falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
SculptSearchSphereData data = {
.ss = ss,
.sd = sd,
- .radius_squared = SQUARE(ss->cache->radius * radius_scale),
+ .radius_squared = ss->cache ? SQUARE(ss->cache->radius * radius_scale) : ss->cursor_radius,
.original = use_original,
};
BKE_pbvh_search_gather(ss->pbvh, sculpt_search_sphere_cb, &data, &nodes, r_totnode);
@@ -1602,7 +1625,7 @@ static PBVHNode **sculpt_pbvh_gather_generic(Object *ob,
SculptSearchCircleData data = {
.ss = ss,
.sd = sd,
- .radius_squared = SQUARE(ss->cache->radius * radius_scale),
+ .radius_squared = ss->cache ? SQUARE(ss->cache->radius * radius_scale) : ss->cursor_radius,
.original = use_original,
.dist_ray_to_aabb_precalc = &dist_ray_to_aabb_precalc,
};
@@ -1964,10 +1987,14 @@ typedef struct SculptDoBrushSmoothGridDataChunk {
typedef struct {
SculptSession *ss;
const float *ray_start;
+ const float *ray_normal;
bool hit;
float depth;
bool original;
+ int active_vertex_index;
+ float *face_normal;
+
struct IsectRayPrecalc isect_precalc;
} SculptRaycastData;
@@ -3987,7 +4014,7 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl
BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings);
}
-void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3])
+void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3])
{
Mesh *me = (Mesh *)ob->data;
float(*ofs)[3] = NULL;
@@ -4349,7 +4376,7 @@ static void sculpt_update_keyblock(Object *ob)
vertCos = ss->orig_cos;
}
else {
- vertCos = BKE_pbvh_get_vertCos(ss->pbvh);
+ vertCos = BKE_pbvh_vert_coords_alloc(ss->pbvh);
}
if (vertCos) {
@@ -4513,7 +4540,7 @@ static void do_tiled(
float orgLoc[3]; /* position of the "prototype" stroke for tiling */
copy_v3_v3(orgLoc, cache->location);
- for (dim = 0; dim < 3; ++dim) {
+ for (dim = 0; dim < 3; dim++) {
if ((sd->paint.symmetry_flags & (PAINT_TILE_X << dim)) && step[dim] > 0) {
start[dim] = (bbMin[dim] - orgLoc[dim] - radius) / step[dim];
end[dim] = (bbMax[dim] - orgLoc[dim] + radius) / step[dim];
@@ -4529,16 +4556,16 @@ static void do_tiled(
/* now do it for all the tiles */
copy_v3_v3_int(cur, start);
- for (cur[0] = start[0]; cur[0] <= end[0]; ++cur[0]) {
- for (cur[1] = start[1]; cur[1] <= end[1]; ++cur[1]) {
- for (cur[2] = start[2]; cur[2] <= end[2]; ++cur[2]) {
+ for (cur[0] = start[0]; cur[0] <= end[0]; cur[0]++) {
+ for (cur[1] = start[1]; cur[1] <= end[1]; cur[1]++) {
+ for (cur[2] = start[2]; cur[2] <= end[2]; cur[2]++) {
if (!cur[0] && !cur[1] && !cur[2]) {
continue; /* skip tile at orgLoc, this was already handled before all others */
}
++cache->tile_pass;
- for (dim = 0; dim < 3; ++dim) {
+ for (dim = 0; dim < 3; dim++) {
cache->location[dim] = cur[dim] * step[dim] + orgLoc[dim];
cache->plane_offset[dim] = cur[dim] * step[dim];
}
@@ -5154,10 +5181,11 @@ static bool sculpt_any_smooth_mode(const Brush *brush, StrokeCache *cache, int s
static void sculpt_stroke_modifiers_check(const bContext *C, Object *ob, const Brush *brush)
{
SculptSession *ss = ob->sculpt;
+ View3D *v3d = CTX_wm_view3d(C);
- if (ss->kb || ss->modifiers_active) {
+ bool need_pmap = sculpt_any_smooth_mode(brush, ss->cache, 0);
+ if (ss->kb || ss->modifiers_active || (!BKE_sculptsession_use_pbvh_draw(ob, v3d) && need_pmap)) {
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
- bool need_pmap = sculpt_any_smooth_mode(brush, ss->cache, 0);
BKE_sculpt_update_object_for_edit(depsgraph, ob, need_pmap, false);
}
}
@@ -5186,8 +5214,11 @@ static void sculpt_raycast_cb(PBVHNode *node, void *data_v, float *tmin)
origco,
use_origco,
srd->ray_start,
+ srd->ray_normal,
&srd->isect_precalc,
- &srd->depth)) {
+ &srd->depth,
+ &srd->active_vertex_index,
+ srd->face_normal)) {
srd->hit = 1;
*tmin = srd->depth;
}
@@ -5275,6 +5306,120 @@ static float sculpt_raycast_init(ViewContext *vc,
return dist;
}
+/* Gets the normal, location and active vertex location of the geometry under the cursor. This also
+ * updates
+ * the active vertex and cursor related data of the SculptSession using the mouse position */
+bool sculpt_cursor_geometry_info_update(bContext *C,
+ SculptCursorGeometryInfo *out,
+ const float mouse[2],
+ bool use_sampled_normal)
+{
+ Scene *scene = CTX_data_scene(C);
+ Sculpt *sd = scene->toolsettings->sculpt;
+ Object *ob;
+ SculptSession *ss;
+ ViewContext vc;
+ const Brush *brush = BKE_paint_brush(BKE_paint_get_active_from_context(C));
+ float ray_start[3], ray_end[3], ray_normal[3], depth, face_normal[3], sampled_normal[3],
+ mat[3][3];
+ float viewDir[3] = {0.0f, 0.0f, 1.0f};
+ int totnode;
+ bool original = false, hit = false;
+
+ ED_view3d_viewcontext_init(C, &vc);
+
+ ob = vc.obact;
+ ss = ob->sculpt;
+
+ if (!ss->pbvh) {
+ copy_v3_fl(out->location, 0.0f);
+ copy_v3_fl(out->normal, 0.0f);
+ copy_v3_fl(out->active_vertex_co, 0.0f);
+ return false;
+ }
+
+ /* PBVH raycast to get active vertex and face normal */
+ depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
+ sculpt_stroke_modifiers_check(C, ob, brush);
+
+ SculptRaycastData srd = {
+ .original = original,
+ .ss = ob->sculpt,
+ .hit = 0,
+ .ray_start = ray_start,
+ .ray_normal = ray_normal,
+ .depth = depth,
+ .face_normal = face_normal,
+ };
+ isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
+ BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
+
+ /* Cursor is not over the mesh, return default values */
+ if (!srd.hit) {
+ copy_v3_fl(out->location, 0.0f);
+ copy_v3_fl(out->normal, 0.0f);
+ copy_v3_fl(out->active_vertex_co, 0.0f);
+ return false;
+ }
+
+ /* Update the active vertex of the SculptSession */
+ ss->active_vertex_index = srd.active_vertex_index;
+
+ copy_v3_v3(out->active_vertex_co, sculpt_vertex_co_get(ss, srd.active_vertex_index));
+ copy_v3_v3(out->location, ray_normal);
+ mul_v3_fl(out->location, srd.depth);
+ add_v3_v3(out->location, ray_start);
+
+ /* Option to return the face normal directly for performance o accuracy reasons */
+ if (!use_sampled_normal) {
+ copy_v3_v3(out->normal, srd.face_normal);
+ return hit;
+ }
+
+ /* Sampled normal calculation */
+ const float radius_scale = 1.0f;
+ float radius;
+
+ /* Update cursor data in SculptSession */
+ invert_m4_m4(ob->imat, ob->obmat);
+ copy_m3_m4(mat, vc.rv3d->viewinv);
+ mul_m3_v3(mat, viewDir);
+ copy_m3_m4(mat, ob->imat);
+ mul_m3_v3(mat, viewDir);
+ normalize_v3_v3(ss->cursor_view_normal, viewDir);
+ copy_v3_v3(ss->cursor_normal, srd.face_normal);
+ copy_v3_v3(ss->cursor_location, out->location);
+ ss->rv3d = vc.rv3d;
+
+ if (!BKE_brush_use_locked_size(scene, brush)) {
+ radius = paint_calc_object_space_radius(&vc, out->location, BKE_brush_size_get(scene, brush));
+ }
+ else {
+ radius = BKE_brush_unprojected_radius_get(scene, brush);
+ }
+ ss->cursor_radius = radius;
+
+ PBVHNode **nodes = sculpt_pbvh_gather_generic(ob, sd, brush, original, radius_scale, &totnode);
+
+ /* In case there are no nodes under the cursor, return the face normal */
+ if (!totnode) {
+ MEM_freeN(nodes);
+ copy_v3_v3(out->normal, srd.face_normal);
+ return true;
+ }
+
+ /* Calculate the sampled normal */
+ if (sculpt_pbvh_calc_area_normal(brush, ob, nodes, totnode, true, sampled_normal)) {
+ copy_v3_v3(out->normal, sampled_normal);
+ }
+ else {
+ /* Use face normal when there are no vertices to sample inside the cursor radius */
+ copy_v3_v3(out->normal, srd.face_normal);
+ }
+ MEM_freeN(nodes);
+ return true;
+}
+
/* Do a raycast in the tree to find the 3d brush location
* (This allows us to ignore the GL depth buffer)
* Returns 0 if the ray doesn't hit the mesh, non-zero otherwise
@@ -5284,7 +5429,7 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
Object *ob;
SculptSession *ss;
StrokeCache *cache;
- float ray_start[3], ray_end[3], ray_normal[3], depth;
+ float ray_start[3], ray_end[3], ray_normal[3], depth, face_normal[3];
bool original;
ViewContext vc;
@@ -5302,14 +5447,21 @@ bool sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2])
depth = sculpt_raycast_init(&vc, mouse, ray_start, ray_end, ray_normal, original);
+ if (BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) {
+ BM_mesh_elem_table_ensure(ss->bm, BM_VERT);
+ BM_mesh_elem_index_ensure(ss->bm, BM_VERT);
+ }
+
bool hit = false;
{
SculptRaycastData srd;
srd.ss = ob->sculpt;
srd.ray_start = ray_start;
+ srd.ray_normal = ray_normal;
srd.hit = 0;
srd.depth = depth;
srd.original = original;
+ srd.face_normal = face_normal;
isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
BKE_pbvh_raycast(ss->pbvh, sculpt_raycast_cb, &srd, ray_start, ray_normal, srd.original);
@@ -5577,7 +5729,6 @@ static void sculpt_stroke_update_step(bContext *C,
}
do_symmetrical_brush_actions(sd, ob, do_brush_action, ups);
-
sculpt_combine_proxies(sd, ob);
/* hack to fix noise texture tearing mesh */
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index e646accf108..9f1cb7a53a4 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -34,9 +34,7 @@
#include "BKE_pbvh.h"
struct KeyBlock;
-struct Main;
struct Object;
-struct SculptOrigVertData;
struct SculptUndoNode;
struct bContext;
@@ -47,7 +45,18 @@ bool sculpt_poll(struct bContext *C);
bool sculpt_poll_view3d(struct bContext *C);
/* Stroke */
+
+typedef struct SculptCursorGeometryInfo {
+ float location[3];
+ float normal[3];
+ float active_vertex_co[3];
+} SculptCursorGeometryInfo;
+
bool sculpt_stroke_get_location(struct bContext *C, float out[3], const float mouse[2]);
+bool sculpt_cursor_geometry_info_update(bContext *C,
+ SculptCursorGeometryInfo *out,
+ const float mouse[2],
+ bool use_sampled_normal);
/* Dynamic topology */
void sculpt_pbvh_clear(Object *ob);
@@ -164,6 +173,7 @@ typedef struct SculptThreadedTaskData {
float (*area_cos)[3];
float (*area_nos)[3];
int *count;
+ bool any_vertex_sampled;
ThreadMutex mutex;
@@ -228,7 +238,7 @@ float tex_strength(struct SculptSession *ss,
const int thread_id);
/* just for vertex paint. */
-void sculpt_pbvh_calc_area_normal(const struct Brush *brush,
+bool sculpt_pbvh_calc_area_normal(const struct Brush *brush,
Object *ob,
PBVHNode **nodes,
int totnode,
@@ -342,7 +352,7 @@ SculptUndoNode *sculpt_undo_get_node(PBVHNode *node);
void sculpt_undo_push_begin(const char *name);
void sculpt_undo_push_end(void);
-void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]);
+void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]);
void sculpt_update_object_bounding_box(struct Object *ob);
diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c
index 3a3487227a3..cb8afd5d7fa 100644
--- a/source/blender/editors/sculpt_paint/sculpt_undo.c
+++ b/source/blender/editors/sculpt_paint/sculpt_undo.c
@@ -189,7 +189,7 @@ static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, Sculpt
/* pbvh uses it's own mvert array, so coords should be */
/* propagated to pbvh here */
- BKE_pbvh_apply_vertCos(ss->pbvh, vertCos, ss->kb->totelem);
+ BKE_pbvh_vert_coords_apply(ss->pbvh, vertCos, ss->kb->totelem);
MEM_freeN(vertCos);
}
diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c
index 51231ccf634..4e710d31cbb 100644
--- a/source/blender/editors/sound/sound_ops.c
+++ b/source/blender/editors/sound/sound_ops.c
@@ -710,7 +710,7 @@ static void SOUND_OT_mixdown(wmOperatorType *ot)
FILE_TYPE_FOLDER | FILE_TYPE_SOUND,
FILE_SPECIAL,
FILE_SAVE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
#ifdef WITH_AUDASPACE
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index bc7f8a0f79d..5ceaefd6309 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -220,7 +220,7 @@ static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
PointerRNA oldptr;
oldptr = RNA_property_pointer_get(&ptr, prop);
- oldact = (bAction *)oldptr.id.data;
+ oldact = (bAction *)oldptr.owner_id;
/* stash the old action to prevent it from being lost */
if (ptr.type == &RNA_AnimData) {
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index a7b6f399187..0c57113956d 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -352,179 +352,231 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* ************************************************************************* */
/* Timeline - Caches */
-void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
+static bool timeline_cache_is_hidden_by_setting(SpaceAction *saction, PTCacheID *pid)
{
- PTCacheID *pid;
- ListBase pidlist;
- const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize);
- float yoffs = 0.f;
-
- if (!(saction->cache_display & TIME_CACHE_DISPLAY) || (!ob)) {
- return;
+ switch (pid->type) {
+ case PTCACHE_TYPE_SOFTBODY:
+ if ((saction->cache_display & TIME_CACHE_SOFTBODY) == 0) {
+ return true;
+ }
+ break;
+ case PTCACHE_TYPE_PARTICLES:
+ if ((saction->cache_display & TIME_CACHE_PARTICLES) == 0) {
+ return true;
+ }
+ break;
+ case PTCACHE_TYPE_CLOTH:
+ if ((saction->cache_display & TIME_CACHE_CLOTH) == 0) {
+ return true;
+ }
+ break;
+ case PTCACHE_TYPE_SMOKE_DOMAIN:
+ case PTCACHE_TYPE_SMOKE_HIGHRES:
+ if ((saction->cache_display & TIME_CACHE_SMOKE) == 0) {
+ return true;
+ }
+ break;
+ case PTCACHE_TYPE_DYNAMICPAINT:
+ if ((saction->cache_display & TIME_CACHE_DYNAMICPAINT) == 0) {
+ return true;
+ }
+ break;
+ case PTCACHE_TYPE_RIGIDBODY:
+ if ((saction->cache_display & TIME_CACHE_RIGIDBODY) == 0) {
+ return true;
+ }
+ break;
}
+ return false;
+}
- BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
+static void timeline_cache_color_get(PTCacheID *pid, float color[4])
+{
+ switch (pid->type) {
+ case PTCACHE_TYPE_SOFTBODY:
+ color[0] = 1.0;
+ color[1] = 0.4;
+ color[2] = 0.02;
+ color[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_PARTICLES:
+ color[0] = 1.0;
+ color[1] = 0.1;
+ color[2] = 0.02;
+ color[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_CLOTH:
+ color[0] = 0.1;
+ color[1] = 0.1;
+ color[2] = 0.75;
+ color[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_SMOKE_DOMAIN:
+ case PTCACHE_TYPE_SMOKE_HIGHRES:
+ color[0] = 0.2;
+ color[1] = 0.2;
+ color[2] = 0.2;
+ color[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_DYNAMICPAINT:
+ color[0] = 1.0;
+ color[1] = 0.1;
+ color[2] = 0.75;
+ color[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_RIGIDBODY:
+ color[0] = 1.0;
+ color[1] = 0.6;
+ color[2] = 0.0;
+ color[3] = 0.1;
+ break;
+ default:
+ color[0] = 1.0;
+ color[1] = 0.0;
+ color[2] = 1.0;
+ color[3] = 0.1;
+ BLI_assert(0);
+ break;
+ }
+}
- uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+static void timeline_cache_modify_color_based_on_state(PointCache *cache, float color[4])
+{
+ if (cache->flag & PTCACHE_BAKED) {
+ color[0] -= 0.4f;
+ color[1] -= 0.4f;
+ color[2] -= 0.4f;
+ }
+ else if (cache->flag & PTCACHE_OUTDATED) {
+ color[0] += 0.4f;
+ color[1] += 0.4f;
+ color[2] += 0.4f;
+ }
+}
- /* iterate over pointcaches on the active object, and draw each one's range */
- for (pid = pidlist.first; pid; pid = pid->next) {
- float col[4];
+static bool timeline_cache_find_next_cached_segment(PointCache *cache,
+ int search_start_frame,
+ int *r_segment_start,
+ int *r_segment_end)
+{
+ int offset = cache->startframe;
+ int current = search_start_frame;
- switch (pid->type) {
- case PTCACHE_TYPE_SOFTBODY:
- if (!(saction->cache_display & TIME_CACHE_SOFTBODY)) {
- continue;
- }
- break;
- case PTCACHE_TYPE_PARTICLES:
- if (!(saction->cache_display & TIME_CACHE_PARTICLES)) {
- continue;
- }
- break;
- case PTCACHE_TYPE_CLOTH:
- if (!(saction->cache_display & TIME_CACHE_CLOTH)) {
- continue;
- }
- break;
- case PTCACHE_TYPE_SMOKE_DOMAIN:
- case PTCACHE_TYPE_SMOKE_HIGHRES:
- if (!(saction->cache_display & TIME_CACHE_SMOKE)) {
- continue;
- }
- break;
- case PTCACHE_TYPE_DYNAMICPAINT:
- if (!(saction->cache_display & TIME_CACHE_DYNAMICPAINT)) {
- continue;
- }
- break;
- case PTCACHE_TYPE_RIGIDBODY:
- if (!(saction->cache_display & TIME_CACHE_RIGIDBODY)) {
- continue;
- }
- break;
+ /* Find segment start frame. */
+ while (true) {
+ if (current > cache->endframe) {
+ return false;
}
-
- if (pid->cache->cached_frames == NULL) {
- continue;
+ if (cache->cached_frames[current - offset]) {
+ *r_segment_start = current;
+ break;
}
+ current++;
+ }
- GPU_matrix_push();
- GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HANDLE_HEIGHT + yoffs);
- GPU_matrix_scale_2f(1.0, cache_draw_height);
-
- switch (pid->type) {
- case PTCACHE_TYPE_SOFTBODY:
- col[0] = 1.0;
- col[1] = 0.4;
- col[2] = 0.02;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_PARTICLES:
- col[0] = 1.0;
- col[1] = 0.1;
- col[2] = 0.02;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_CLOTH:
- col[0] = 0.1;
- col[1] = 0.1;
- col[2] = 0.75;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_SMOKE_DOMAIN:
- case PTCACHE_TYPE_SMOKE_HIGHRES:
- col[0] = 0.2;
- col[1] = 0.2;
- col[2] = 0.2;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_DYNAMICPAINT:
- col[0] = 1.0;
- col[1] = 0.1;
- col[2] = 0.75;
- col[3] = 0.1;
- break;
- case PTCACHE_TYPE_RIGIDBODY:
- col[0] = 1.0;
- col[1] = 0.6;
- col[2] = 0.0;
- col[3] = 0.1;
- break;
- default:
- col[0] = 1.0;
- col[1] = 0.0;
- col[2] = 1.0;
- col[3] = 0.1;
- BLI_assert(0);
- break;
+ /* Find segment end frame. */
+ while (true) {
+ if (current > cache->endframe) {
+ *r_segment_end = current - 1;
+ return true;
+ }
+ if (!cache->cached_frames[current - offset]) {
+ *r_segment_end = current - 1;
+ return true;
}
+ current++;
+ }
+}
+
+static uint timeline_cache_segments_count(PointCache *cache)
+{
+ uint count = 0;
+
+ int current = cache->startframe;
+ int segment_start;
+ int segment_end;
+ while (timeline_cache_find_next_cached_segment(cache, current, &segment_start, &segment_end)) {
+ count++;
+ current = segment_end + 1;
+ }
+
+ return count;
+}
- const int sta = pid->cache->startframe, end = pid->cache->endframe;
+static void timeline_cache_draw_cached_segments(PointCache *cache, uint pos_id)
+{
+ uint segments_count = timeline_cache_segments_count(cache);
+ if (segments_count == 0) {
+ return;
+ }
- GPU_blend(true);
+ immBeginAtMost(GPU_PRIM_TRIS, segments_count * 6);
- immUniformColor4fv(col);
- immRectf(pos, (float)sta, 0.0, (float)end, 1.0);
+ int current = cache->startframe;
+ int segment_start;
+ int segment_end;
+ while (timeline_cache_find_next_cached_segment(cache, current, &segment_start, &segment_end)) {
+ immRectf_fast(pos_id, segment_start - 0.5f, 0, segment_end + 0.5f, 1.0f);
+ current = segment_end + 1;
+ }
- col[3] = 0.4f;
- if (pid->cache->flag & PTCACHE_BAKED) {
- col[0] -= 0.4f;
- col[1] -= 0.4f;
- col[2] -= 0.4f;
- }
- else if (pid->cache->flag & PTCACHE_OUTDATED) {
- col[0] += 0.4f;
- col[1] += 0.4f;
- col[2] += 0.4f;
- }
+ immEnd();
+}
- immUniformColor4fv(col);
+static void timeline_cache_draw_single(PTCacheID *pid, float y_offset, float height, uint pos_id)
+{
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HANDLE_HEIGHT + y_offset);
+ GPU_matrix_scale_2f(1.0, height);
- {
- /* draw a quad for each chunk of consecutive cached frames */
- const int chunk_tot = 32;
- int chunk_len = 0;
- int ista = 0, iend = -1;
+ float color[4];
+ timeline_cache_color_get(pid, color);
- for (int i = sta; i <= end; i++) {
- if (pid->cache->cached_frames[i - sta]) {
- if (chunk_len == 0) {
- immBeginAtMost(GPU_PRIM_TRIS, chunk_tot * 6);
- }
- if (ista > iend) {
- chunk_len++;
- ista = i;
- }
- iend = i;
- }
- else {
- if (ista <= iend) {
- immRectf_fast(pos, (float)ista - 0.5f, 0.0f, (float)iend + 0.5f, 1.0f);
- iend = ista - 1;
- }
- if (chunk_len >= chunk_tot) {
- immEnd();
- chunk_len = 0;
- }
- }
- }
- if (ista <= iend) {
- immRectf_fast(pos, (float)ista - 0.5f, 0.0f, (float)iend + 0.5f, 1.0f);
- }
- if (chunk_len != 0) {
- immEnd();
- }
+ immUniformColor4fv(color);
+ immRectf(pos_id, (float)pid->cache->startframe, 0.0, (float)pid->cache->endframe, 1.0);
+
+ color[3] = 0.4f;
+ timeline_cache_modify_color_based_on_state(pid->cache, color);
+ immUniformColor4fv(color);
+
+ timeline_cache_draw_cached_segments(pid->cache, pos_id);
+
+ GPU_matrix_pop();
+}
+
+void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
+{
+ if ((saction->cache_display & TIME_CACHE_DISPLAY) == 0 || ob == NULL) {
+ return;
+ }
+
+ ListBase pidlist;
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
+
+ uint pos_id = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ GPU_blend(true);
+
+ /* Iterate over pointcaches on the active object, and draw each one's range. */
+ float y_offset = 0.0f;
+ const float cache_draw_height = 4.0f * UI_DPI_FAC * U.pixelsize;
+ for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) {
+ if (timeline_cache_is_hidden_by_setting(saction, pid)) {
+ continue;
}
- GPU_blend(false);
+ if (pid->cache->cached_frames == NULL) {
+ continue;
+ }
- GPU_matrix_pop();
+ timeline_cache_draw_single(pid, y_offset, cache_draw_height, pos_id);
- yoffs += cache_draw_height;
+ y_offset += cache_draw_height;
}
+ GPU_blend(false);
immUnbindProgram();
BLI_freelistN(&pidlist);
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
index eaca7968a34..c227b794ae7 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -28,9 +28,7 @@ struct ARegion;
struct ARegionType;
struct Object;
struct Scene;
-struct ScrArea;
struct SpaceAction;
-struct View2D;
struct bAnimContext;
struct bContext;
struct wmOperatorType;
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 9e2634b183a..cbf4d0628e6 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -1717,22 +1717,26 @@ static void mouse_action_keys(bAnimContext *ac,
/* Highlight GPencil Layer */
if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_GPLAYER) {
+ bGPdata *gpd = (bGPdata *)ale->id;
bGPDlayer *gpl = ale->data;
gpl->flag |= GP_LAYER_SELECT;
- // gpencil_layer_setactive(gpd, gpl);
+ /* Update other layer status. */
+ if (BKE_gpencil_layer_getactive(gpd) != gpl) {
+ BKE_gpencil_layer_setactive(gpd, gpl);
+ BKE_gpencil_layer_autolock_set(gpd);
+ WM_main_add_notifier(NC_GPENCIL | ND_DATA | NA_EDITED, NULL);
+ }
}
}
else if (ac->datatype == ANIMCONT_MASK) {
/* deselect all other channels first */
ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
- /* Highlight GPencil Layer */
if (ale != NULL && ale->data != NULL && ale->type == ANIMTYPE_MASKLAYER) {
MaskLayer *masklay = ale->data;
masklay->flag |= MASK_LAYERFLAG_SELECT;
- // gpencil_layer_setactive(gpd, gpl);
}
}
}
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index 3c879b03126..1685852dd02 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -373,7 +373,7 @@ static void saction_channel_region_message_subscribe(const struct bContext *UNUS
* so just whitelist the entire structs for updates
*/
{
- wmMsgParams_RNA msg_key_params = {{{0}}};
+ wmMsgParams_RNA msg_key_params = {{0}};
StructRNA *type_array[] = {
&RNA_DopeSheet, /* dopesheet filters */
diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c
index 78d5ed0f98a..56a0f472010 100644
--- a/source/blender/editors/space_buttons/buttons_context.c
+++ b/source/blender/editors/space_buttons/buttons_context.c
@@ -76,7 +76,7 @@ static int set_pointer_type(ButsContextPath *path, bContextDataResult *result, S
ptr = &path->ptr[a];
if (RNA_struct_is_a(ptr->type, type)) {
- CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
+ CTX_data_pointer_set(result, ptr->owner_id, ptr->type, ptr->data);
return 1;
}
}
@@ -930,7 +930,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
if (ct->user && ct->user->ptr.data) {
ButsTextureUser *user = ct->user;
- CTX_data_pointer_set(result, user->ptr.id.data, user->ptr.type, user->ptr.data);
+ CTX_data_pointer_set(result, user->ptr.owner_id, user->ptr.type, user->ptr.data);
}
return 1;
@@ -1018,7 +1018,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
PointerRNA *ptr = get_pointer_type(path, &RNA_ParticleSettings);
if (ptr && ptr->data) {
- CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, ptr->data);
+ CTX_data_pointer_set(result, ptr->owner_id, &RNA_ParticleSettings, ptr->data);
return 1;
}
else {
@@ -1027,7 +1027,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
if (ptr && ptr->data) {
ParticleSettings *part = ((ParticleSystem *)ptr->data)->part;
- CTX_data_pointer_set(result, ptr->id.data, &RNA_ParticleSettings, part);
+ CTX_data_pointer_set(result, ptr->owner_id, &RNA_ParticleSettings, part);
return 1;
}
}
@@ -1285,8 +1285,8 @@ ID *buttons_context_id_path(const bContext *C)
}
}
- if (ptr->id.data) {
- return ptr->id.data;
+ if (ptr->owner_id) {
+ return ptr->owner_id;
}
}
}
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index 500efe4bb4d..3ea6d183969 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -103,7 +103,7 @@ static int file_browse_exec(bContext *C, wmOperator *op)
/* add slash for directories, important for some properties */
if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) {
const bool is_relative = RNA_boolean_get(op->ptr, "relative_path");
- id = fbo->ptr.id.data;
+ id = fbo->ptr.owner_id;
BLI_strncpy(path, str, FILE_MAX);
BLI_path_abs(path, id ? ID_BLEND_PATH(bmain, id) : BKE_main_blendfile_path(bmain));
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 87ea011e0a7..03c8fbb4e66 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -385,7 +385,7 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg)
if (user->ptr.type == &RNA_ParticleSettingsTextureSlot) {
/* stupid exception for particle systems which still uses influence
* from the old texture system, set the active texture slots as well */
- ParticleSettings *part = user->ptr.id.data;
+ ParticleSettings *part = (ParticleSettings *)user->ptr.owner_id;
int a;
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 b3690bf2fe3..6008d06e376 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -404,8 +404,6 @@ static void buttons_area_listener(wmWindow *UNUSED(win),
buttons_area_redraw(sa, BCONTEXT_DATA); /* autotexpace flag */
break;
case ND_POSE:
- buttons_area_redraw(sa, BCONTEXT_DATA);
- break;
case ND_BONE_ACTIVE:
case ND_BONE_SELECT:
buttons_area_redraw(sa, BCONTEXT_BONE);
@@ -567,7 +565,7 @@ static void buttons_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id,
int i;
for (i = 0; i < path->len; i++) {
- if (path->ptr[i].id.data == old_id) {
+ if (path->ptr[i].owner_id == old_id) {
break;
}
}
diff --git a/source/blender/editors/space_clip/clip_dopesheet_draw.c b/source/blender/editors/space_clip/clip_dopesheet_draw.c
index 599a92ff77f..3c2d3eb1d97 100644
--- a/source/blender/editors/space_clip/clip_dopesheet_draw.c
+++ b/source/blender/editors/space_clip/clip_dopesheet_draw.c
@@ -222,8 +222,9 @@ void clip_draw_dopesheet_main(SpaceClip *sc, ARegion *ar, Scene *scene)
format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
GPU_program_point_size(true);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ immUniform1f("outline_scale", 1.0f);
immUniform2f(
"ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
immBegin(GPU_PRIM_POINTS, keyframe_len);
diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c
index 999255aef88..f5c02dbd724 100644
--- a/source/blender/editors/space_console/space_console.c
+++ b/source/blender/editors/space_console/space_console.c
@@ -26,6 +26,7 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
+#include "BKE_global.h"
#include "BKE_context.h"
#include "BKE_screen.h"
@@ -173,7 +174,7 @@ static void id_drop_copy(wmDrag *drag, wmDropBox *drop)
ID *id = WM_drag_ID(drag, 0);
/* copy drag path to properties */
- char *text = RNA_path_full_ID_py(id);
+ char *text = RNA_path_full_ID_py(G_MAIN, id);
RNA_string_set(drop->ptr, "text", text);
MEM_freeN(text);
}
diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c
index 3a6d59c1dbf..0083fc244d8 100644
--- a/source/blender/editors/space_file/file_draw.c
+++ b/source/blender/editors/space_file/file_draw.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include "BLI_blenlib.h"
+#include "BLI_fileops_types.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
@@ -77,234 +78,6 @@ static char *file_draw_tooltip_func(bContext *UNUSED(C), void *argN, const char
return BLI_strdup(dyn_tooltip);
}
-/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d.
- * The controls are laid out as follows:
- *
- * -------------------------------------------
- * | Directory input | execute |
- * -------------------------------------------
- * | Filename input | + | - | cancel |
- * -------------------------------------------
- *
- * The input widgets will stretch to fill any excess space.
- * When there isn't enough space for all controls to be shown, they are
- * hidden in this order: x/-, execute/cancel, input widgets.
- */
-void file_draw_buttons(const bContext *C, ARegion *ar)
-{
- /* Button layout. */
- const int max_x = ar->winx - 10;
- const int line1_y = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
- const int line2_y = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN);
- const int input_minw = 20;
- const int btn_h = UI_UNIT_Y;
- const int btn_fn_w = UI_UNIT_X;
- const int btn_minw = 80;
- const int btn_margin = 20;
- const int separator = 4;
-
- /* Additional locals. */
- char uiblockstr[32];
- int loadbutton;
- int fnumbuttons;
- int min_x = 10;
- int chan_offs = 0;
- int available_w = max_x - min_x;
- int line1_w = available_w;
- int line2_w = available_w;
-
- uiBut *but;
- uiBlock *block;
- SpaceFile *sfile = CTX_wm_space_file(C);
- FileSelectParams *params = ED_fileselect_get_params(sfile);
- ARegion *artmp;
- const bool is_browse_only = (sfile->op == NULL);
-
- /* Initialize UI block. */
- BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar);
- block = UI_block_begin(C, ar, uiblockstr, UI_EMBOSS);
-
- /* exception to make space for collapsed region icon */
- for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) {
- if (artmp->regiontype == RGN_TYPE_TOOLS && artmp->flag & RGN_FLAG_HIDDEN) {
- chan_offs = 16;
- min_x += chan_offs;
- available_w -= chan_offs;
- }
- }
-
- /* Is there enough space for the execute / cancel buttons? */
-
- if (is_browse_only) {
- loadbutton = 0;
- }
- else {
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin;
- CLAMP_MIN(loadbutton, btn_minw);
- if (available_w <= loadbutton + separator + input_minw) {
- loadbutton = 0;
- }
- }
-
- if (loadbutton) {
- line1_w -= (loadbutton + separator);
- line2_w = line1_w;
- }
-
- /* Is there enough space for file number increment/decrement buttons? */
- fnumbuttons = 2 * btn_fn_w;
- if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) {
- fnumbuttons = 0;
- }
- else {
- line2_w -= (fnumbuttons + separator);
- }
-
- /* Text input fields for directory and file. */
- if (available_w > 0) {
- const struct FileDirEntry *file = sfile->files ?
- filelist_file(sfile->files, params->active_file) :
- NULL;
- int overwrite_alert = file_draw_check_exists(sfile);
- const bool is_active_dir = file && (file->typeflag & FILE_TYPE_FOLDER);
-
- /* callbacks for operator check functions */
- UI_block_func_set(block, file_draw_check_cb, NULL, NULL);
-
- but = uiDefBut(block,
- UI_BTYPE_TEXT,
- -1,
- "",
- min_x,
- line1_y,
- line1_w - chan_offs,
- btn_h,
- params->dir,
- 0.0,
- (float)FILE_MAX,
- 0,
- 0,
- TIP_("File path"));
- UI_but_func_complete_set(but, autocomplete_directory, NULL);
- UI_but_flag_enable(but, UI_BUT_NO_UTF8);
- UI_but_flag_disable(but, UI_BUT_UNDO);
- UI_but_funcN_set(but, file_directory_enter_handle, NULL, but);
-
- /* TODO, directory editing is non-functional while a library is loaded
- * until this is properly supported just disable it. */
- if (sfile->files && filelist_lib(sfile->files)) {
- UI_but_flag_enable(but, UI_BUT_DISABLED);
- }
-
- if ((params->flag & FILE_DIRSEL_ONLY) == 0) {
- but = uiDefBut(
- block,
- UI_BTYPE_TEXT,
- -1,
- "",
- min_x,
- line2_y,
- line2_w - chan_offs,
- btn_h,
- is_active_dir ? (char *)"" : params->file,
- 0.0,
- (float)FILE_MAXFILE,
- 0,
- 0,
- TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name")));
- UI_but_func_complete_set(but, autocomplete_file, NULL);
- UI_but_flag_enable(but, UI_BUT_NO_UTF8);
- UI_but_flag_disable(but, UI_BUT_UNDO);
- /* silly workaround calling NFunc to ensure this does not get called
- * immediate ui_apply_but_func but only after button deactivates */
- UI_but_funcN_set(but, file_filename_enter_handle, NULL, but);
-
- /* check if this overrides a file and if the operator option is used */
- if (overwrite_alert) {
- UI_but_flag_enable(but, UI_BUT_REDALERT);
- }
- }
-
- /* clear func */
- UI_block_func_set(block, NULL, NULL, NULL);
- }
-
- /* Filename number increment / decrement buttons. */
- if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) {
- UI_block_align_begin(block);
- but = uiDefIconButO(block,
- UI_BTYPE_BUT,
- "FILE_OT_filenum",
- 0,
- ICON_REMOVE,
- min_x + line2_w + separator - chan_offs,
- line2_y,
- btn_fn_w,
- btn_h,
- TIP_("Decrement the filename number"));
- RNA_int_set(UI_but_operator_ptr_get(but), "increment", -1);
-
- but = uiDefIconButO(block,
- UI_BTYPE_BUT,
- "FILE_OT_filenum",
- 0,
- ICON_ADD,
- min_x + line2_w + separator + btn_fn_w - chan_offs,
- line2_y,
- btn_fn_w,
- btn_h,
- TIP_("Increment the filename number"));
- RNA_int_set(UI_but_operator_ptr_get(but), "increment", 1);
- UI_block_align_end(block);
- }
-
- /* Execute / cancel buttons. */
- if (loadbutton) {
- const struct FileDirEntry *file = sfile->files ?
- filelist_file(sfile->files, params->active_file) :
- NULL;
- char const *str_exec;
-
- if (file && FILENAME_IS_PARENT(file->relpath)) {
- str_exec = IFACE_("Parent Directory");
- }
- else if (file && file->typeflag & FILE_TYPE_DIR) {
- str_exec = IFACE_("Open Directory");
- }
- else {
- str_exec = params->title; /* params->title is already translated! */
- }
-
- but = uiDefButO(block,
- UI_BTYPE_BUT,
- "FILE_OT_execute",
- WM_OP_EXEC_REGION_WIN,
- str_exec,
- max_x - loadbutton,
- line1_y,
- loadbutton,
- btn_h,
- "");
- /* Just a display hint. */
- UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
-
- uiDefButO(block,
- UI_BTYPE_BUT,
- "FILE_OT_cancel",
- WM_OP_EXEC_REGION_WIN,
- IFACE_("Cancel"),
- max_x - loadbutton,
- line2_y,
- loadbutton,
- btn_h,
- "");
- }
-
- UI_block_end(C, block);
- UI_block_draw(C, block);
-}
-
static void draw_tile(int sx, int sy, int width, int height, int colorid, int shade)
{
float color[4];
@@ -349,7 +122,7 @@ static void file_draw_string(int sx,
rcti rect;
char fname[FILE_MAXFILE];
- if (string[0] == '\0') {
+ if (string[0] == '\0' || width < 1) {
return;
}
@@ -362,7 +135,7 @@ static void file_draw_string(int sx,
/* no text clipping needed, UI_fontstyle_draw does it but is a bit too strict
* (for buttons it works) */
rect.xmin = sx;
- rect.xmax = (int)(sx + ceil(width + 5.0f / UI_DPI_FAC));
+ rect.xmax = sx + round_fl_to_int(width);
rect.ymin = sy - height;
rect.ymax = sy;
@@ -404,8 +177,8 @@ static void file_draw_preview(uiBlock *block,
float scaledx, scaledy;
float scale;
int ex, ey;
- bool use_dropshadow = !is_icon && (typeflags & FILE_TYPE_IMAGE);
- float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ bool use_dropshadow = !is_icon &&
+ (typeflags & (FILE_TYPE_IMAGE | FILE_TYPE_MOVIE | FILE_TYPE_BLENDER));
BLI_assert(imb != NULL);
@@ -442,13 +215,27 @@ static void file_draw_preview(uiBlock *block,
/* shadow */
if (use_dropshadow) {
- UI_draw_box_shadow(220, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ UI_draw_box_shadow(128, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
}
GPU_blend(true);
- /* the image */
- if (!is_icon && typeflags & FILE_TYPE_FTFONT) {
+ /* the large image */
+
+ float col[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ if (is_icon) {
+ /* File and Folder icons draw with lowered opacity until we add themes */
+ col[3] = 0.6f;
+ /* Use dark images if background is light */
+ float bg[3];
+ UI_GetThemeColor3fv(TH_BACK, bg);
+ if (rgb_to_grayscale(bg) > 0.5f) {
+ col[0] = 0;
+ col[1] = 0;
+ col[2] = 0;
+ }
+ }
+ else if (typeflags & FILE_TYPE_FTFONT) {
UI_GetThemeColor4fv(TH_TEXT, col);
}
@@ -477,30 +264,61 @@ static void file_draw_preview(uiBlock *block,
GPU_blend_set_func_separate(
GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
- if (icon) {
- UI_icon_draw_ex((float)xco + (7 * UI_DPI_FAC),
- (float)yco + (7 * UI_DPI_FAC),
- icon,
- icon_aspect,
- 1.0f,
- 0.0f,
- NULL,
- false);
+ if (icon && (icon != ICON_FILE_FONT)) {
+ /* size of center icon is scaled to fit container and UI scale */
+ float icon_x, icon_y;
+
+ if (is_icon) {
+ const float icon_size = 16.0f / icon_aspect * U.dpi_fac;
+ float icon_opacity = MIN2(icon_aspect, 0.7);
+ uchar icon_color[4] = {255, 255, 255, 255};
+ float bg[3];
+ /* base this off theme color of file or folder later */
+ UI_GetThemeColor3fv(TH_BACK, bg);
+ if (rgb_to_grayscale(bg) > 0.5f) {
+ icon_color[0] = 0;
+ icon_color[1] = 0;
+ icon_color[2] = 0;
+ }
+ icon_x = xco + (ex / 2.0f) - (icon_size / 2.0f);
+ icon_y = yco + (ey / 2.0f) - (icon_size * ((typeflags & FILE_TYPE_DIR) ? 0.78f : 0.65f));
+ UI_icon_draw_ex(
+ icon_x, icon_y, icon, icon_aspect / U.dpi_fac, icon_opacity, 0.0f, icon_color, false);
+ }
+ else {
+ const uchar dark[4] = {0, 0, 0, 255};
+ const uchar light[4] = {255, 255, 255, 255};
+
+ /* Smaller, fainter icon for preview image thumbnail. */
+ icon_x = xco + (2.0f * UI_DPI_FAC);
+ icon_y = yco + (2.0f * UI_DPI_FAC);
+
+ UI_icon_draw_ex(icon_x + 1, icon_y - 1, icon, 1.0f / U.dpi_fac, 0.2f, 0.0f, dark, false);
+ UI_icon_draw_ex(icon_x, icon_y, icon, 1.0f / U.dpi_fac, 0.6f, 0.0f, light, false);
+ }
}
/* border */
if (use_dropshadow) {
GPUVertFormat *format = immVertexFormat();
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint pos_attr = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col_attr = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- immUniformColor4f(0.0f, 0.0f, 0.0f, 0.4f);
- imm_draw_box_wire_2d(pos, (float)xco, (float)yco, (float)(xco + ex), (float)(yco + ey));
+ immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
+ immBegin(GPU_PRIM_LINE_LOOP, 4);
+ immAttr4f(col_attr, 1.0f, 1.0f, 1.0f, 0.15f);
+ immVertex2f(pos_attr, (float)xco + 1, (float)(yco + ey));
+ immAttr4f(col_attr, 1.0f, 1.0f, 1.0f, 0.2f);
+ immVertex2f(pos_attr, (float)(xco + ex), (float)(yco + ey));
+ immAttr4f(col_attr, 0.0f, 0.0f, 0.0f, 0.2f);
+ immVertex2f(pos_attr, (float)(xco + ex), (float)yco + 1);
+ immAttr4f(col_attr, 0.0f, 0.0f, 0.0f, 0.3f);
+ immVertex2f(pos_attr, (float)xco + 1, (float)yco + 1);
+ immEnd();
immUnbindProgram();
}
but = uiDefBut(block, UI_BTYPE_LABEL, 0, "", xco, yco, ex, ey, NULL, 0.0, 0.0, 0, 0, NULL);
- UI_but_func_tooltip_set(but, file_draw_tooltip_func, BLI_strdup(path));
/* dragregion */
if (drag) {
@@ -557,6 +375,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname)
static void draw_background(FileLayout *layout, View2D *v2d)
{
+ const int item_height = layout->tile_h + (2 * layout->tile_border_y);
int i;
int sy;
@@ -565,9 +384,11 @@ static void draw_background(FileLayout *layout, View2D *v2d)
immUniformThemeColorShade(TH_BACK, -7);
/* alternating flat shade background */
- for (i = 0; (i <= layout->rows); i += 2) {
- sy = (int)v2d->cur.ymax - i * (layout->tile_h + 2 * layout->tile_border_y) -
- layout->tile_border_y;
+ for (i = 2; (i <= layout->rows + 1); i += 2) {
+ sy = (int)v2d->cur.ymax - layout->offset_top - i * item_height - layout->tile_border_y;
+
+ /* Offsett pattern slightly to add scroll effect. */
+ sy += round_fl_to_int(item_height * (v2d->tot.ymax - v2d->cur.ymax) / item_height);
immRectf(pos,
v2d->cur.xmin,
@@ -632,6 +453,176 @@ static void draw_dividers(FileLayout *layout, View2D *v2d)
}
}
+static void draw_columnheader_background(const FileLayout *layout, const View2D *v2d)
+{
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, 11);
+
+ immRectf(pos,
+ v2d->cur.xmin,
+ v2d->cur.ymax - layout->attribute_column_header_h,
+ v2d->cur.xmax,
+ v2d->cur.ymax);
+
+ immUnbindProgram();
+}
+
+static void draw_columnheader_columns(const FileSelectParams *params,
+ FileLayout *layout,
+ const View2D *v2d,
+ const uchar text_col[4])
+{
+ const float divider_pad = 0.2 * layout->attribute_column_header_h;
+ int sx = v2d->cur.xmin, sy = v2d->cur.ymax;
+
+ for (FileAttributeColumnType column_type = 0; column_type < ATTRIBUTE_COLUMN_MAX;
+ column_type++) {
+ if (!file_attribute_column_type_enabled(params, column_type)) {
+ continue;
+ }
+ const FileAttributeColumn *column = &layout->attribute_columns[column_type];
+
+ /* Active sort type triangle */
+ if (params->sort == column->sort_type) {
+ float tri_color[4];
+
+ rgba_uchar_to_float(tri_color, text_col);
+ UI_draw_icon_tri(sx + column->width - (0.3f * U.widget_unit) -
+ ATTRIBUTE_COLUMN_PADDING / 2.0f,
+ sy + (0.1f * U.widget_unit) - (layout->attribute_column_header_h / 2),
+ (params->flag & FILE_SORT_INVERT) ? 't' : 'v',
+ tri_color);
+ }
+
+ file_draw_string(sx + ATTRIBUTE_COLUMN_PADDING,
+ sy - layout->tile_border_y,
+ IFACE_(column->name),
+ column->width - 2 * ATTRIBUTE_COLUMN_PADDING,
+ layout->attribute_column_header_h - layout->tile_border_y,
+ UI_STYLE_TEXT_LEFT,
+ text_col);
+
+ /* Separator line */
+ if (column_type != COLUMN_NAME) {
+ uint pos = GPU_vertformat_attr_add(
+ immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, -10);
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, sx - 1, sy - divider_pad);
+ immVertex2f(pos, sx - 1, sy - layout->attribute_column_header_h + divider_pad);
+ immEnd();
+ immUnbindProgram();
+ }
+
+ sx += column->width;
+ }
+
+ /* Vertical separator lines line */
+ {
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ immUniformThemeColorShade(TH_BACK, -10);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, v2d->cur.xmin, sy);
+ immVertex2f(pos, v2d->cur.xmax, sy);
+ immVertex2f(pos, v2d->cur.xmin, sy - layout->attribute_column_header_h);
+ immVertex2f(pos, v2d->cur.xmax, sy - layout->attribute_column_header_h);
+ immEnd();
+ immUnbindProgram();
+ }
+}
+
+/**
+ * Updates the stat string stored in file->entry if necessary.
+ */
+static const char *filelist_get_details_column_string(FileAttributeColumnType column,
+ const FileDirEntry *file,
+ const bool small_size,
+ const bool update_stat_strings)
+{
+ switch (column) {
+ case COLUMN_DATETIME:
+ if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
+ if ((file->entry->datetime_str[0] == '\0') || update_stat_strings) {
+ char date[FILELIST_DIRENTRY_DATE_LEN], time[FILELIST_DIRENTRY_TIME_LEN];
+ bool is_today, is_yesterday;
+
+ BLI_filelist_entry_datetime_to_string(
+ NULL, file->entry->time, small_size, time, date, &is_today, &is_yesterday);
+
+ if (is_today || is_yesterday) {
+ BLI_strncpy(date, is_today ? N_("Today") : N_("Yesterday"), sizeof(date));
+ }
+ BLI_snprintf(
+ file->entry->datetime_str, sizeof(file->entry->datetime_str), "%s %s", date, time);
+ }
+
+ return file->entry->datetime_str;
+ }
+ break;
+ case COLUMN_SIZE:
+ if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
+ !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
+ if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
+ BLI_filelist_entry_size_to_string(
+ NULL, file->entry->size, small_size, file->entry->size_str);
+ }
+
+ return file->entry->size_str;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static void draw_details_columns(const FileSelectParams *params,
+ const FileLayout *layout,
+ const FileDirEntry *file,
+ const int pos_x,
+ const int pos_y,
+ const uchar text_col[4])
+{
+ const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
+ const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size);
+ int sx = pos_x - layout->tile_border_x - (UI_UNIT_X * 0.1f), sy = pos_y;
+
+ for (FileAttributeColumnType column_type = 0; column_type < ATTRIBUTE_COLUMN_MAX;
+ column_type++) {
+ const FileAttributeColumn *column = &layout->attribute_columns[column_type];
+
+ /* Name column is not a detail column (should already be drawn), always skip here. */
+ if (column_type == COLUMN_NAME) {
+ sx += column->width;
+ continue;
+ }
+ if (!file_attribute_column_type_enabled(params, column_type)) {
+ continue;
+ }
+
+ const char *str = filelist_get_details_column_string(
+ column_type, file, small_size, update_stat_strings);
+
+ if (str) {
+ file_draw_string(sx + ATTRIBUTE_COLUMN_PADDING,
+ sy - layout->tile_border_y,
+ IFACE_(str),
+ column->width - 2 * ATTRIBUTE_COLUMN_PADDING,
+ layout->tile_h,
+ column->text_align,
+ text_col);
+ }
+
+ sx += column->width;
+ }
+}
+
void file_draw_list(const bContext *C, ARegion *ar)
{
SpaceFile *sfile = CTX_wm_space_file(C);
@@ -652,18 +643,14 @@ void file_draw_list(const bContext *C, ARegion *ar)
bool is_icon;
eFontStyle_Align align;
bool do_drag;
- int column_space = 0.6f * UI_UNIT_X;
unsigned char text_col[4];
- const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
- const bool update_stat_strings = small_size != SMALL_SIZE_CHECK(layout->curr_size);
- const float thumb_icon_aspect = sqrtf(64.0f / (float)(params->thumbnail_size));
+ const bool draw_columnheader = (params->display == FILE_VERTICALDISPLAY);
+ const float thumb_icon_aspect = MIN2(64.0f / (float)(params->thumbnail_size), 1.0f);
numfiles = filelist_files_ensure(files);
if (params->display != FILE_IMGDISPLAY) {
-
draw_background(layout, v2d);
-
draw_dividers(layout, v2d);
}
@@ -679,13 +666,14 @@ void file_draw_list(const bContext *C, ARegion *ar)
numfiles_layout += layout->rows;
}
else {
- numfiles_layout += layout->columns;
+ numfiles_layout += layout->flow_columns;
}
filelist_file_cache_slidingwindow_set(files, numfiles_layout);
- textwidth = (FILE_IMGDISPLAY == params->display) ? layout->tile_w :
- (int)layout->column_widths[COLUMN_NAME];
+ textwidth = (FILE_IMGDISPLAY == params->display) ?
+ layout->tile_w :
+ round_fl_to_int(layout->attribute_columns[COLUMN_NAME].width);
textheight = (int)(layout->textheight * 3.0 / 2.0 + 0.5);
align = (FILE_IMGDISPLAY == params->display) ? UI_STYLE_TEXT_CENTER : UI_STYLE_TEXT_LEFT;
@@ -719,11 +707,16 @@ void file_draw_list(const bContext *C, ARegion *ar)
BLF_batch_draw_begin();
+ UI_GetThemeColor4ubv(TH_TEXT, text_col);
+
for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) {
unsigned int file_selflag;
char path[FILE_MAX_LIBEXTRA];
+ int padx = 0.1f * UI_UNIT_X;
+ int icon_ofs = 0;
+
ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
- sx += (int)(v2d->tot.xmin + 0.1f * UI_UNIT_X);
+ sx += (int)(v2d->tot.xmin + padx);
sy = (int)(v2d->tot.ymax - sy);
file = filelist_file(files, i);
@@ -737,15 +730,14 @@ void file_draw_list(const bContext *C, ARegion *ar)
int colorid = (file_selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK;
int shade = (params->highlight_file == i) || (file_selflag & FILE_SEL_HIGHLIGHTED) ? 35 :
0;
+ const short width = ELEM(params->display, FILE_VERTICALDISPLAY, FILE_HORIZONTALDISPLAY) ?
+ layout->tile_w - (2 * padx) :
+ layout->tile_w;
BLI_assert(i == 0 || !FILENAME_IS_CURRPAR(file->relpath));
- draw_tile(sx,
- sy - 1,
- layout->tile_w + 4,
- sfile->layout->tile_h + layout->tile_border_y,
- colorid,
- shade);
+ draw_tile(
+ sx, sy - 1, width, sfile->layout->tile_h + layout->tile_border_y, colorid, shade);
}
}
UI_draw_roundbox_corner_set(UI_CNR_NONE);
@@ -778,38 +770,28 @@ void file_draw_list(const bContext *C, ARegion *ar)
file_draw_icon(block,
path,
sx,
- sy - (UI_UNIT_Y / 6),
+ sy - layout->tile_border_y,
filelist_geticon(files, i, true),
ICON_DEFAULT_WIDTH_SCALE,
ICON_DEFAULT_HEIGHT_SCALE,
do_drag);
- sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
+ icon_ofs += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X;
}
- UI_GetThemeColor4ubv(TH_TEXT, text_col);
-
if (file_selflag & FILE_SEL_EDITING) {
uiBut *but;
- short width;
-
- if (params->display == FILE_SHORTDISPLAY) {
- width = layout->tile_w - (ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X);
- }
- else if (params->display == FILE_LONGDISPLAY) {
- width = layout->column_widths[COLUMN_NAME] + (column_space * 3.5f);
- }
- else {
- BLI_assert(params->display == FILE_IMGDISPLAY);
- width = textwidth;
- }
+ const short width = (params->display == FILE_IMGDISPLAY) ?
+ textwidth :
+ layout->attribute_columns[COLUMN_NAME].width -
+ ATTRIBUTE_COLUMN_PADDING;
but = uiDefBut(block,
UI_BTYPE_TEXT,
1,
"",
- sx,
+ sx + icon_ofs,
sy - layout->tile_h - 0.15f * UI_UNIT_X,
- width,
+ width - icon_ofs,
textheight,
sfile->params->renamefile,
1.0f,
@@ -825,74 +807,19 @@ void file_draw_list(const bContext *C, ARegion *ar)
sfile->files, file, FILE_SEL_REMOVE, FILE_SEL_EDITING, CHECK_ALL);
}
}
-
- if (!(file_selflag & FILE_SEL_EDITING)) {
- int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight :
- sy;
- file_draw_string(sx + 1, tpos, file->name, (float)textwidth, textheight, align, text_col);
- }
-
- sx += (int)layout->column_widths[COLUMN_NAME] + column_space;
- if (params->display == FILE_SHORTDISPLAY) {
- if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
- !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
- if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
- BLI_filelist_entry_size_to_string(
- NULL, file->entry->size, small_size, file->entry->size_str);
- }
- file_draw_string(sx,
- sy,
- file->entry->size_str,
- layout->column_widths[COLUMN_SIZE],
- layout->tile_h,
- align,
- text_col);
- }
- sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
+ else {
+ const int txpos = (params->display == FILE_IMGDISPLAY) ? sx : sx + 1 + icon_ofs;
+ const int typos = (params->display == FILE_IMGDISPLAY) ?
+ sy - layout->tile_h + layout->textheight :
+ sy - layout->tile_border_y;
+ const int twidth = (params->display == FILE_IMGDISPLAY) ?
+ textwidth :
+ textwidth - 1 - icon_ofs - padx - layout->tile_border_x;
+ file_draw_string(txpos, typos, file->name, (float)twidth, textheight, align, text_col);
}
- else if (params->display == FILE_LONGDISPLAY) {
- if (!(file->typeflag & FILE_TYPE_BLENDERLIB) && !FILENAME_IS_CURRPAR(file->relpath)) {
- if ((file->entry->date_str[0] == '\0') || update_stat_strings) {
- BLI_filelist_entry_datetime_to_string(
- NULL, file->entry->time, small_size, file->entry->time_str, file->entry->date_str);
- }
- file_draw_string(sx,
- sy,
- file->entry->date_str,
- layout->column_widths[COLUMN_DATE],
- layout->tile_h,
- align,
- text_col);
- sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
- file_draw_string(sx,
- sy,
- file->entry->time_str,
- layout->column_widths[COLUMN_TIME],
- layout->tile_h,
- align,
- text_col);
- sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
- }
- else {
- sx += (int)layout->column_widths[COLUMN_DATE] + column_space;
- sx += (int)layout->column_widths[COLUMN_TIME] + column_space;
- }
- if ((file->typeflag & (FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) ||
- !(file->typeflag & (FILE_TYPE_DIR | FILE_TYPE_BLENDERLIB))) {
- if ((file->entry->size_str[0] == '\0') || update_stat_strings) {
- BLI_filelist_entry_size_to_string(
- NULL, file->entry->size, small_size, file->entry->size_str);
- }
- file_draw_string(sx,
- sy,
- file->entry->size_str,
- layout->column_widths[COLUMN_SIZE],
- layout->tile_h,
- align,
- text_col);
- }
- sx += (int)layout->column_widths[COLUMN_SIZE] + column_space;
+ if (params->display != FILE_IMGDISPLAY) {
+ draw_details_columns(params, layout, file, sx, sy, text_col);
}
}
@@ -901,5 +828,11 @@ void file_draw_list(const bContext *C, ARegion *ar)
UI_block_end(C, block);
UI_block_draw(C, block);
+ /* Draw last, on top of file list. */
+ if (draw_columnheader) {
+ draw_columnheader_background(layout, v2d);
+ draw_columnheader_columns(params, layout, v2d, text_col);
+ }
+
layout->curr_size = params->thumbnail_size;
}
diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h
index bad25511dd5..61f13098783 100644
--- a/source/blender/editors/space_file/file_intern.h
+++ b/source/blender/editors/space_file/file_intern.h
@@ -30,9 +30,11 @@ struct ARegion;
struct ARegionType;
struct FileSelectParams;
struct SpaceFile;
+struct View2D;
/* file_ops.c */
struct ARegion *file_tools_region(struct ScrArea *sa);
+struct ARegion *file_tool_props_region(struct ScrArea *sa);
/* file_draw.c */
#define TILE_BORDER_X (UI_UNIT_X / 4)
@@ -42,9 +44,10 @@ struct ARegion *file_tools_region(struct ScrArea *sa);
#define IMASEL_BUTTONS_HEIGHT (UI_UNIT_Y * 2)
#define IMASEL_BUTTONS_MARGIN (UI_UNIT_Y / 6)
+#define ATTRIBUTE_COLUMN_PADDING (0.5f * UI_UNIT_X)
+
#define SMALL_SIZE_CHECK(_size) ((_size) < 64) /* Related to FileSelectParams.thumbnail_size. */
-void file_draw_buttons(const bContext *C, ARegion *ar);
void file_calc_previews(const bContext *C, ARegion *ar);
void file_draw_list(const bContext *C, ARegion *ar);
@@ -64,6 +67,7 @@ typedef enum WalkSelectDirection {
} WalkSelectDirections;
void FILE_OT_highlight(struct wmOperatorType *ot);
+void FILE_OT_sort_column_ui_context(struct wmOperatorType *ot);
void FILE_OT_select(struct wmOperatorType *ot);
void FILE_OT_select_walk(struct wmOperatorType *ot);
void FILE_OT_select_all(struct wmOperatorType *ot);
@@ -112,6 +116,16 @@ void file_operator_to_sfile(bContext *C, struct SpaceFile *sfile, struct wmOpera
/* filesel.c */
void fileselect_file_set(SpaceFile *sfile, const int index);
+bool file_attribute_column_type_enabled(const FileSelectParams *params,
+ FileAttributeColumnType column);
+bool file_attribute_column_header_is_inside(const struct View2D *v2d,
+ const FileLayout *layout,
+ int x,
+ int y);
+FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d,
+ const FileSelectParams *params,
+ FileLayout *layout,
+ int x);
float file_string_width(const char *str);
float file_font_pointsize(void);
diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c
index eb5f02b6e13..5168300d21e 100644
--- a/source/blender/editors/space_file/file_ops.c
+++ b/source/blender/editors/space_file/file_ops.c
@@ -78,7 +78,12 @@ static FileSelection find_file_mouse_rect(SpaceFile *sfile, ARegion *ar, const r
BLI_rctf_rcti_copy(&rect_region_fl, rect_region);
+ /* Okay, manipulating v2d rects here is hacky... */
+ v2d->mask.ymax -= sfile->layout->offset_top;
+ v2d->cur.ymax -= sfile->layout->offset_top;
UI_view2d_region_to_view_rctf(v2d, &rect_region_fl, &rect_view_fl);
+ v2d->mask.ymax += sfile->layout->offset_top;
+ v2d->cur.ymax += sfile->layout->offset_top;
BLI_rcti_init(&rect_view,
(int)(v2d->tot.xmin + rect_view_fl.xmin),
@@ -190,7 +195,6 @@ static FileSelect file_select_do(bContext *C, int selected_idx, bool do_diropen)
const bool is_parent_dir = FILENAME_IS_PARENT(file->relpath);
if (do_diropen == false) {
- params->file[0] = '\0';
retval = FILE_SELECT_DIR;
}
/* the path is too long and we are not going up! */
@@ -262,8 +266,8 @@ static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const i
cur->ymax = cur->ymin + ar->winy;
}
/* up */
- else if (cur->ymax < rect.ymax) {
- cur->ymax = rect.ymax + layout->tile_border_y;
+ else if ((cur->ymax - layout->offset_top) < rect.ymax) {
+ cur->ymax = rect.ymax + layout->tile_border_y + layout->offset_top;
cur->ymin = cur->ymax - ar->winy;
}
/* left - also use if tile is wider than viewbounds so view is aligned to file name */
@@ -278,7 +282,7 @@ static void file_ensure_inside_viewbounds(ARegion *ar, SpaceFile *sfile, const i
}
else {
BLI_assert(cur->xmin <= rect.xmin && cur->xmax >= rect.xmax && cur->ymin <= rect.ymin &&
- cur->ymax >= rect.ymax);
+ (cur->ymax - layout->offset_top) >= rect.ymax);
changed = false;
}
@@ -384,7 +388,7 @@ static int file_box_select_modal(bContext *C, wmOperator *op, const wmEvent *eve
if (result == OPERATOR_RUNNING_MODAL) {
WM_operator_properties_border_to_rcti(op, &rect);
- BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
+ ED_fileselect_layout_isect_rect(sfile->layout, &ar->v2d, &rect, &rect);
sel = file_selection_get(C, &rect, 0);
if ((sel.first != params->sel_first) || (sel.last != params->sel_last)) {
@@ -440,13 +444,13 @@ static int file_box_select_exec(bContext *C, wmOperator *op)
file_deselect_all(sfile, FILE_SEL_SELECTED);
}
- BLI_rcti_isect(&(ar->v2d.mask), &rect, &rect);
+ ED_fileselect_layout_isect_rect(sfile->layout, &ar->v2d, &rect, &rect);
ret = file_select(C, &rect, select ? FILE_SEL_ADD : FILE_SEL_REMOVE, false, false);
/* unselect '..' parent entry - it's not supposed to be selected if more than
* one file is selected */
- filelist_entry_select_index_set(sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ filelist_entry_parent_select_set(sfile->files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
if (FILE_SELECT_DIR == ret) {
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL);
@@ -493,7 +497,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
rect.xmin = rect.xmax = event->mval[0];
rect.ymin = rect.ymax = event->mval[1];
- if (!BLI_rcti_isect_pt(&ar->v2d.mask, rect.xmin, rect.ymin)) {
+ if (!ED_fileselect_layout_is_inside_pt(sfile->layout, &ar->v2d, rect.xmin, rect.ymin)) {
return OPERATOR_CANCELLED;
}
@@ -514,8 +518,7 @@ static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (extend) {
/* unselect '..' parent entry - it's not supposed to be selected if more
* than one file is selected */
- filelist_entry_select_index_set(
- sfile->files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ filelist_entry_parent_select_set(sfile->files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
}
if (FILE_SELECT_DIR == ret) {
@@ -580,6 +583,11 @@ static bool file_walk_select_selection_set(bContext *C,
BLI_assert(params);
+ if (numfiles == 0) {
+ /* No files visible, nothing to do. */
+ return false;
+ }
+
if (has_selection) {
if (extend && filelist_entry_select_index_get(files, active_old, CHECK_ALL) &&
filelist_entry_select_index_get(files, active_new, CHECK_ALL)) {
@@ -609,7 +617,7 @@ static bool file_walk_select_selection_set(bContext *C,
}
/* select first file */
else if (ELEM(direction, FILE_SELECT_WALK_DOWN, FILE_SELECT_WALK_RIGHT)) {
- params->active_file = active = extend ? 1 : 0;
+ params->active_file = active = 0;
}
else {
BLI_assert(0);
@@ -626,7 +634,7 @@ static bool file_walk_select_selection_set(bContext *C,
/* unselect '..' parent entry - it's not supposed to be selected if more
* than one file is selected */
- filelist_entry_select_index_set(files, 0, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ filelist_entry_parent_select_set(files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
}
else {
/* deselect all first */
@@ -641,11 +649,6 @@ static bool file_walk_select_selection_set(bContext *C,
if (fill) {
FileSelection sel = {MIN2(active, last_sel), MAX2(active, last_sel)};
- /* clamping selection to not include '..' parent entry */
- if (sel.first == 0) {
- sel.first = 1;
- }
-
/* fill selection between last and first selected file */
filelist_entries_select_index_range_set(
files, &sel, deselect ? FILE_SEL_REMOVE : FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
@@ -653,6 +656,12 @@ static bool file_walk_select_selection_set(bContext *C,
if (deselect) {
filelist_entry_select_index_set(files, active, FILE_SEL_ADD, FILE_SEL_SELECTED, CHECK_ALL);
}
+
+ /* unselect '..' parent entry - it's not supposed to be selected if more
+ * than one file is selected */
+ if ((sel.last - sel.first) > 1) {
+ filelist_entry_parent_select_set(files, FILE_SEL_REMOVE, FILE_SEL_SELECTED, CHECK_ALL);
+ }
}
else {
filelist_entry_select_index_set(
@@ -688,10 +697,15 @@ static bool file_walk_select_do(bContext *C,
/* *** get all needed files for handling selection *** */
+ if (numfiles == 0) {
+ /* No files visible, nothing to do. */
+ return false;
+ }
+
if (has_selection) {
ARegion *ar = CTX_wm_region(C);
FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
- const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->columns;
+ const int idx_shift = (layout->flag & FILE_LAYOUT_HOR) ? layout->rows : layout->flow_columns;
if ((layout->flag & FILE_LAYOUT_HOR && direction == FILE_SELECT_WALK_UP) ||
(layout->flag & FILE_LAYOUT_VER && direction == FILE_SELECT_WALK_LEFT)) {
@@ -718,7 +732,7 @@ static bool file_walk_select_do(bContext *C,
BLI_assert(0);
}
- if (!IN_RANGE(active_new, 0, numfiles)) {
+ if (!IN_RANGE(active_new, -1, numfiles)) {
if (extend) {
/* extend to invalid file -> abort */
return false;
@@ -1185,7 +1199,7 @@ int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
mx -= ar->winrct.xmin;
my -= ar->winrct.ymin;
- if (BLI_rcti_isect_pt(&ar->v2d.mask, mx, my)) {
+ if (ED_fileselect_layout_is_inside_pt(sfile->layout, v2d, mx, my)) {
float fx, fy;
int highlight_file;
@@ -1234,6 +1248,53 @@ void FILE_OT_highlight(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active;
}
+static int file_column_sort_ui_context_invoke(bContext *C,
+ wmOperator *UNUSED(op),
+ const wmEvent *event)
+{
+ const ARegion *ar = CTX_wm_region(C);
+ SpaceFile *sfile = CTX_wm_space_file(C);
+
+ if (file_attribute_column_header_is_inside(
+ &ar->v2d, sfile->layout, event->mval[0], event->mval[1])) {
+ const FileAttributeColumnType column_type = file_attribute_column_type_find_isect(
+ &ar->v2d, sfile->params, sfile->layout, event->mval[0]);
+
+ if (column_type != COLUMN_NONE) {
+ const FileAttributeColumn *column = &sfile->layout->attribute_columns[column_type];
+
+ if (column->sort_type != FILE_SORT_NONE) {
+ if (sfile->params->sort == column->sort_type) {
+ /* Already sorting by selected column -> toggle sort invert (three state logic). */
+ sfile->params->flag ^= FILE_SORT_INVERT;
+ }
+ else {
+ sfile->params->sort = column->sort_type;
+ sfile->params->flag &= ~FILE_SORT_INVERT;
+ }
+
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ }
+ }
+ }
+
+ return OPERATOR_PASS_THROUGH;
+}
+
+void FILE_OT_sort_column_ui_context(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Sort from Column";
+ ot->description = "Change sorting to use column under cursor";
+ ot->idname = "FILE_OT_sort_column_ui_context";
+
+ /* api callbacks */
+ ot->invoke = file_column_sort_ui_context_invoke;
+ ot->poll = ED_operator_file_active;
+
+ ot->flag = OPTYPE_INTERNAL;
+}
+
int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused))
{
wmWindowManager *wm = CTX_wm_manager(C);
@@ -1713,7 +1774,7 @@ static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const w
/* Number of items in a block (i.e. lines in a column in horizontal layout, or columns in a line
* in vertical layout).
*/
- const int items_block_size = is_horizontal ? sfile->layout->rows : sfile->layout->columns;
+ const int items_block_size = is_horizontal ? sfile->layout->rows : sfile->layout->flow_columns;
/* Scroll offset is the first file in the row/column we are editing in. */
if (sfile->scroll_offset == 0) {
@@ -1998,7 +2059,6 @@ void FILE_OT_directory_new(struct wmOperatorType *ot)
ot->idname = "FILE_OT_directory_new";
/* api callbacks */
- ot->invoke = WM_operator_confirm;
ot->exec = file_directory_new_exec;
ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
@@ -2260,10 +2320,29 @@ ARegion *file_tools_region(ScrArea *sa)
arnew->regiontype = RGN_TYPE_TOOLS;
arnew->alignment = RGN_ALIGN_LEFT;
- ar = MEM_callocN(sizeof(ARegion), "tool props for file");
- BLI_insertlinkafter(&sa->regionbase, arnew, ar);
- ar->regiontype = RGN_TYPE_TOOL_PROPS;
- ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
+ return arnew;
+}
+
+ARegion *file_tool_props_region(ScrArea *sa)
+{
+ ARegion *ar, *arnew;
+
+ if ((ar = BKE_area_find_region_type(sa, RGN_TYPE_TOOL_PROPS)) != NULL) {
+ return ar;
+ }
+
+ /* add subdiv level; after execute region */
+ ar = BKE_area_find_region_type(sa, RGN_TYPE_EXECUTE);
+
+ /* is error! */
+ if (ar == NULL) {
+ return NULL;
+ }
+
+ arnew = MEM_callocN(sizeof(ARegion), "tool props for file");
+ BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+ arnew->regiontype = RGN_TYPE_TOOL_PROPS;
+ arnew->alignment = RGN_ALIGN_RIGHT;
return arnew;
}
@@ -2292,6 +2371,17 @@ void FILE_OT_bookmark_toggle(struct wmOperatorType *ot)
ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
}
+static bool file_filenum_poll(bContext *C)
+{
+ SpaceFile *sfile = CTX_wm_space_file(C);
+
+ if (!ED_operator_file_active(C)) {
+ return false;
+ }
+
+ return sfile->params && (sfile->params->action_type == FILE_SAVE);
+}
+
/**
* Looks for a string of digits within name (using BLI_stringdec) and adjusts it by add.
*/
@@ -2349,7 +2439,7 @@ void FILE_OT_filenum(struct wmOperatorType *ot)
/* api callbacks */
ot->exec = file_filenum_exec;
- ot->poll = ED_operator_file_active; /* <- important, handler is on window level */
+ ot->poll = file_filenum_poll;
/* props */
RNA_def_int(ot->srna, "increment", 1, -100, 100, "Increment", "", -100, 100);
diff --git a/source/blender/editors/space_file/file_panels.c b/source/blender/editors/space_file/file_panels.c
index d9a6e70121f..b41358f575f 100644
--- a/source/blender/editors/space_file/file_panels.c
+++ b/source/blender/editors/space_file/file_panels.c
@@ -103,6 +103,7 @@ void file_panels_register(ARegionType *art)
strcpy(pt->idname, "FILE_PT_operator");
strcpy(pt->label, N_("Operator"));
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
+ pt->flag = PNL_NO_HEADER;
pt->poll = file_panel_operator_poll;
pt->draw_header = file_panel_operator_header;
pt->draw = file_panel_operator;
diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c
index f7dda1defe8..46302e0d087 100644
--- a/source/blender/editors/space_file/filelist.c
+++ b/source/blender/editors/space_file/filelist.c
@@ -329,25 +329,20 @@ enum {
FL_IS_PENDING = 1 << 2,
FL_NEED_SORTING = 1 << 3,
FL_NEED_FILTERING = 1 << 4,
+ FL_SORT_INVERT = 1 << 5,
};
-#define SPECIAL_IMG_SIZE 48
-#define SPECIAL_IMG_ROWS 4
-#define SPECIAL_IMG_COLS 4
+#define SPECIAL_IMG_SIZE 256
+#define SPECIAL_IMG_ROWS 1
+#define SPECIAL_IMG_COLS 6
enum {
- SPECIAL_IMG_FOLDER = 0,
- SPECIAL_IMG_PARENT = 1,
- SPECIAL_IMG_REFRESH = 2,
- SPECIAL_IMG_BLENDFILE = 3,
- SPECIAL_IMG_SOUNDFILE = 4,
- SPECIAL_IMG_MOVIEFILE = 5,
- SPECIAL_IMG_PYTHONFILE = 6,
- SPECIAL_IMG_TEXTFILE = 7,
- SPECIAL_IMG_FONTFILE = 8,
- SPECIAL_IMG_UNKNOWNFILE = 9,
- SPECIAL_IMG_LOADING = 10,
- SPECIAL_IMG_BACKUP = 11,
+ SPECIAL_IMG_DOCUMENT = 0,
+ SPECIAL_IMG_FOLDER = 1,
+ SPECIAL_IMG_PARENT = 2,
+ SPECIAL_IMG_DRIVE_FIXED = 3,
+ SPECIAL_IMG_DRIVE_ATTACHED = 4,
+ SPECIAL_IMG_DRIVE_REMOTE = 5,
SPECIAL_IMG_MAX,
};
@@ -369,6 +364,19 @@ static void filelist_cache_clear(FileListEntryCache *cache, size_t new_size);
/* ********** Sort helpers ********** */
+struct FileSortData {
+ bool inverted;
+};
+
+static int compare_apply_inverted(int val, const struct FileSortData *sort_data)
+{
+ return sort_data->inverted ? -val : val;
+}
+
+/**
+ * Handles inverted sorting itself (currently there's nothing to invert), so if this returns non-0,
+ * it should be used as-is and not inverted.
+ */
static int compare_direntry_generic(const FileListInternEntry *entry1,
const FileListInternEntry *entry2)
{
@@ -420,10 +428,11 @@ static int compare_direntry_generic(const FileListInternEntry *entry1,
return 0;
}
-static int compare_name(void *UNUSED(user_data), const void *a1, const void *a2)
+static int compare_name(void *user_data, const void *a1, const void *a2)
{
const FileListInternEntry *entry1 = a1;
const FileListInternEntry *entry2 = a2;
+ const struct FileSortData *sort_data = user_data;
char *name1, *name2;
int ret;
@@ -434,13 +443,14 @@ static int compare_name(void *UNUSED(user_data), const void *a1, const void *a2)
name1 = entry1->name;
name2 = entry2->name;
- return BLI_natstrcmp(name1, name2);
+ return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data);
}
-static int compare_date(void *UNUSED(user_data), const void *a1, const void *a2)
+static int compare_date(void *user_data, const void *a1, const void *a2)
{
const FileListInternEntry *entry1 = a1;
const FileListInternEntry *entry2 = a2;
+ const struct FileSortData *sort_data = user_data;
char *name1, *name2;
int64_t time1, time2;
int ret;
@@ -452,22 +462,23 @@ static int compare_date(void *UNUSED(user_data), const void *a1, const void *a2)
time1 = (int64_t)entry1->st.st_mtime;
time2 = (int64_t)entry2->st.st_mtime;
if (time1 < time2) {
- return 1;
+ return compare_apply_inverted(1, sort_data);
}
if (time1 > time2) {
- return -1;
+ return compare_apply_inverted(-1, sort_data);
}
name1 = entry1->name;
name2 = entry2->name;
- return BLI_natstrcmp(name1, name2);
+ return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data);
}
-static int compare_size(void *UNUSED(user_data), const void *a1, const void *a2)
+static int compare_size(void *user_data, const void *a1, const void *a2)
{
const FileListInternEntry *entry1 = a1;
const FileListInternEntry *entry2 = a2;
+ const struct FileSortData *sort_data = user_data;
char *name1, *name2;
uint64_t size1, size2;
int ret;
@@ -479,22 +490,23 @@ static int compare_size(void *UNUSED(user_data), const void *a1, const void *a2)
size1 = entry1->st.st_size;
size2 = entry2->st.st_size;
if (size1 < size2) {
- return 1;
+ return compare_apply_inverted(1, sort_data);
}
if (size1 > size2) {
- return -1;
+ return compare_apply_inverted(-1, sort_data);
}
name1 = entry1->name;
name2 = entry2->name;
- return BLI_natstrcmp(name1, name2);
+ return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data);
}
-static int compare_extension(void *UNUSED(user_data), const void *a1, const void *a2)
+static int compare_extension(void *user_data, const void *a1, const void *a2)
{
const FileListInternEntry *entry1 = a1;
const FileListInternEntry *entry2 = a2;
+ const struct FileSortData *sort_data = user_data;
char *name1, *name2;
int ret;
@@ -516,10 +528,10 @@ static int compare_extension(void *UNUSED(user_data), const void *a1, const void
return -1;
}
if (entry1->blentype < entry2->blentype) {
- return -1;
+ return compare_apply_inverted(-1, sort_data);
}
if (entry1->blentype > entry2->blentype) {
- return 1;
+ return compare_apply_inverted(1, sort_data);
}
}
else {
@@ -539,48 +551,58 @@ static int compare_extension(void *UNUSED(user_data), const void *a1, const void
}
if ((ret = BLI_strcasecmp(sufix1, sufix2))) {
- return ret;
+ return compare_apply_inverted(ret, sort_data);
}
}
name1 = entry1->name;
name2 = entry2->name;
- return BLI_natstrcmp(name1, name2);
+ return compare_apply_inverted(BLI_strcasecmp_natural(name1, name2), sort_data);
}
void filelist_sort(struct FileList *filelist)
{
if ((filelist->flags & FL_NEED_SORTING) && (filelist->sort != FILE_SORT_NONE)) {
+ void *sort_cb = NULL;
+
switch (filelist->sort) {
case FILE_SORT_ALPHA:
- BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_name, NULL);
+ sort_cb = compare_name;
break;
case FILE_SORT_TIME:
- BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_date, NULL);
+ sort_cb = compare_date;
break;
case FILE_SORT_SIZE:
- BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_size, NULL);
+ sort_cb = compare_size;
break;
case FILE_SORT_EXTENSION:
- BLI_listbase_sort_r(&filelist->filelist_intern.entries, compare_extension, NULL);
+ sort_cb = compare_extension;
break;
case FILE_SORT_NONE: /* Should never reach this point! */
default:
BLI_assert(0);
break;
}
+ BLI_listbase_sort_r(
+ &filelist->filelist_intern.entries,
+ sort_cb,
+ &(struct FileSortData){.inverted = (filelist->flags & FL_SORT_INVERT) != 0});
filelist_filter_clear(filelist);
filelist->flags &= ~FL_NEED_SORTING;
}
}
-void filelist_setsorting(struct FileList *filelist, const short sort)
+void filelist_setsorting(struct FileList *filelist, const short sort, bool invert_sort)
{
- if (filelist->sort != sort) {
+ const bool was_invert_sort = filelist->flags & FL_SORT_INVERT;
+
+ if ((filelist->sort != sort) || (was_invert_sort != invert_sort)) {
filelist->sort = sort;
filelist->flags |= FL_NEED_SORTING;
+ filelist->flags = invert_sort ? (filelist->flags | FL_SORT_INVERT) :
+ (filelist->flags & ~FL_SORT_INVERT);
}
}
@@ -635,9 +657,9 @@ static bool is_filtered_file(FileListInternEntry *file,
{
bool is_filtered = !is_hidden_file(file->relpath, filter);
- if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) {
+ if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) {
/* We only check for types if some type are enabled in filtering. */
- if (filter->filter) {
+ if (filter->filter && (filter->flags & FLF_DO_FILTER)) {
if (file->typeflag & FILE_TYPE_DIR) {
if (file->typeflag &
(FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
@@ -657,6 +679,7 @@ static bool is_filtered_file(FileListInternEntry *file,
}
}
}
+ /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */
if (is_filtered && (filter->filter_search[0] != '\0')) {
if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
is_filtered = false;
@@ -676,9 +699,9 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis
if (BLO_library_path_explode(path, dir, &group, &name)) {
is_filtered = !is_hidden_file(file->relpath, filter);
- if (is_filtered && (filter->flags & FLF_DO_FILTER) && !FILENAME_IS_CURRPAR(file->relpath)) {
+ if (is_filtered && !FILENAME_IS_CURRPAR(file->relpath)) {
/* We only check for types if some type are enabled in filtering. */
- if (filter->filter || filter->filter_id) {
+ if ((filter->filter || filter->filter_id) && (filter->flags & FLF_DO_FILTER)) {
if (file->typeflag & FILE_TYPE_DIR) {
if (file->typeflag &
(FILE_TYPE_BLENDERLIB | FILE_TYPE_BLENDER | FILE_TYPE_BLENDER_BACKUP)) {
@@ -704,6 +727,7 @@ static bool is_filtered_lib(FileListInternEntry *file, const char *root, FileLis
}
}
}
+ /* If there's a filter string, apply it as filter even if FLF_DO_FILTER is not set. */
if (is_filtered && (filter->filter_search[0] != '\0')) {
if (fnmatch(filter->filter_search, file->relpath, FNM_CASEFOLD) != 0) {
is_filtered = false;
@@ -904,42 +928,12 @@ static ImBuf *filelist_geticon_image_ex(const unsigned int typeflag, const char
if (FILENAME_IS_PARENT(relpath)) {
ibuf = gSpecialFileImages[SPECIAL_IMG_PARENT];
}
- else if (FILENAME_IS_CURRENT(relpath)) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_REFRESH];
- }
else {
ibuf = gSpecialFileImages[SPECIAL_IMG_FOLDER];
}
}
- else if (typeflag & FILE_TYPE_BLENDER) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_BLENDFILE];
- }
- else if (typeflag & FILE_TYPE_BLENDERLIB) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
- }
- else if (typeflag & (FILE_TYPE_MOVIE)) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_MOVIEFILE];
- }
- else if (typeflag & FILE_TYPE_SOUND) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_SOUNDFILE];
- }
- else if (typeflag & FILE_TYPE_PYSCRIPT) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_PYTHONFILE];
- }
- else if (typeflag & FILE_TYPE_FTFONT) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_FONTFILE];
- }
- else if (typeflag & FILE_TYPE_TEXT) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_TEXTFILE];
- }
- else if (typeflag & FILE_TYPE_IMAGE) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_LOADING];
- }
- else if (typeflag & FILE_TYPE_BLENDER_BACKUP) {
- ibuf = gSpecialFileImages[SPECIAL_IMG_BACKUP];
- }
else {
- ibuf = gSpecialFileImages[SPECIAL_IMG_UNKNOWNFILE];
+ ibuf = gSpecialFileImages[SPECIAL_IMG_DOCUMENT];
}
return ibuf;
@@ -1001,10 +995,13 @@ static int filelist_geticon_ex(const int typeflag,
return ICON_FILE_BLANK;
}
else if (typeflag & FILE_TYPE_COLLADA) {
- return ICON_FILE_BLANK;
+ return ICON_FILE_3D;
}
else if (typeflag & FILE_TYPE_ALEMBIC) {
- return ICON_FILE_BLANK;
+ return ICON_FILE_3D;
+ }
+ else if (typeflag & FILE_TYPE_OBJECT_IO) {
+ return ICON_FILE_3D;
}
else if (typeflag & FILE_TYPE_TEXT) {
return ICON_FILE_TEXT;
@@ -1243,7 +1240,8 @@ static void filelist_cache_previews_clear(FileListEntryCache *cache)
BLI_task_pool_cancel(cache->previews_pool);
while ((preview = BLI_thread_queue_pop_timeout(cache->previews_done, 0))) {
- // printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path, preview->img);
+ // printf("%s: DONE %d - %s - %p\n", __func__, preview->index, preview->path,
+ // preview->img);
if (preview->img) {
IMB_freeImBuf(preview->img);
}
@@ -2128,6 +2126,9 @@ int ED_path_extension_type(const char *path)
else if (BLI_path_extension_check(path, ".abc")) {
return FILE_TYPE_ALEMBIC;
}
+ else if (BLI_path_extension_check_n(path, ".obj", ".3ds", ".fbx", ".glb", ".gltf", NULL)) {
+ return FILE_TYPE_OBJECT_IO;
+ }
else if (BLI_path_extension_check_array(path, imb_ext_image)) {
return FILE_TYPE_IMAGE;
}
@@ -2177,9 +2178,9 @@ int ED_file_extension_icon(const char *path)
case FILE_TYPE_BTX:
return ICON_FILE_BLANK;
case FILE_TYPE_COLLADA:
- return ICON_FILE_BLANK;
case FILE_TYPE_ALEMBIC:
- return ICON_FILE_BLANK;
+ case FILE_TYPE_OBJECT_IO:
+ return ICON_FILE_3D;
case FILE_TYPE_TEXT:
return ICON_FILE_TEXT;
default:
@@ -2298,6 +2299,19 @@ unsigned int filelist_entry_select_index_get(FileList *filelist,
return 0;
}
+/**
+ * Set selection of the '..' parent entry, but only if it's actually visible.
+ */
+void filelist_entry_parent_select_set(FileList *filelist,
+ FileSelType select,
+ unsigned int flag,
+ FileCheckType check)
+{
+ if ((filelist->filter_data.flags & FLF_HIDE_PARENT) == 0) {
+ filelist_entry_select_index_set(filelist, 0, select, flag, check);
+ }
+}
+
/* WARNING! dir must be FILE_MAX_LIBEXTRA long! */
bool filelist_islibrary(struct FileList *filelist, char *dir, char **group)
{
diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h
index caf77246797..9b1107294ff 100644
--- a/source/blender/editors/space_file/filelist.h
+++ b/source/blender/editors/space_file/filelist.h
@@ -55,7 +55,7 @@ void folderlist_pushdir(struct ListBase *folderlist, const char *dir);
const char *folderlist_peeklastdir(struct ListBase *folderdist);
int folderlist_clear_next(struct SpaceFile *sfile);
-void filelist_setsorting(struct FileList *filelist, const short sort);
+void filelist_setsorting(struct FileList *filelist, const short sort, bool invert_sort);
void filelist_sort(struct FileList *filelist);
void filelist_setfilter_options(struct FileList *filelist,
@@ -117,6 +117,10 @@ unsigned int filelist_entry_select_get(struct FileList *filelist,
unsigned int filelist_entry_select_index_get(struct FileList *filelist,
const int index,
FileCheckType check);
+void filelist_entry_parent_select_set(struct FileList *filelist,
+ FileSelType select,
+ unsigned int flag,
+ FileCheckType check);
void filelist_setrecursion(struct FileList *filelist, const int recursion_level);
diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c
index db42d007b8e..3223fe0c6ce 100644
--- a/source/blender/editors/space_file/filesel.c
+++ b/source/blender/editors/space_file/filesel.c
@@ -49,6 +49,8 @@
#include "BLI_utildefines.h"
#include "BLI_fnmatch.h"
+#include "BLT_translation.h"
+
#include "BKE_appdir.h"
#include "BKE_context.h"
#include "BKE_main.h"
@@ -69,6 +71,8 @@
#include "file_intern.h"
#include "filelist.h"
+#define VERTLIST_MAJORCOLUMN_WIDTH (25 * UI_UNIT_X)
+
FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile)
{
if (!sfile->params) {
@@ -99,6 +103,8 @@ short ED_fileselect_set_params(SpaceFile *sfile)
sfile->params->filter_glob[0] = '\0';
/* set the default thumbnails size */
sfile->params->thumbnail_size = 128;
+ /* Show size column by default. */
+ sfile->params->details_flags = FILE_DETAILS_SIZE | FILE_DETAILS_DATETIME;
}
params = sfile->params;
@@ -161,6 +167,10 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->flag &= ~FILE_DIRSEL_ONLY;
}
+ if ((prop = RNA_struct_find_property(op->ptr, "hide_props_region"))) {
+ params->flag |= RNA_property_boolean_get(op->ptr, prop) ? FILE_HIDE_TOOL_PROPS : 0;
+ }
+
params->filter = 0;
if ((prop = RNA_struct_find_property(op->ptr, "filter_blender"))) {
params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FILE_TYPE_BLENDER : 0;
@@ -261,6 +271,10 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->sort = FILE_SORT_ALPHA;
}
+ if ((prop = RNA_struct_find_property(op->ptr, "action_type"))) {
+ params->action_type = RNA_property_enum_get(op->ptr, prop);
+ }
+
if (params->display == FILE_DEFAULTDISPLAY) {
if (params->display_previous == FILE_DEFAULTDISPLAY) {
if (U.uiflag & USER_SHOW_THUMBNAILS) {
@@ -268,11 +282,11 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->display = FILE_IMGDISPLAY;
}
else {
- params->display = FILE_SHORTDISPLAY;
+ params->display = FILE_VERTICALDISPLAY;
}
}
else {
- params->display = FILE_SHORTDISPLAY;
+ params->display = FILE_VERTICALDISPLAY;
}
}
else {
@@ -293,7 +307,7 @@ short ED_fileselect_set_params(SpaceFile *sfile)
params->type = FILE_UNIX;
params->flag |= FILE_HIDE_DOT;
params->flag &= ~FILE_DIRSEL_ONLY;
- params->display = FILE_SHORTDISPLAY;
+ params->display = FILE_VERTICALDISPLAY;
params->display_previous = FILE_DEFAULTDISPLAY;
params->sort = FILE_SORT_ALPHA;
params->filter = 0;
@@ -344,7 +358,7 @@ void ED_fileselect_reset_params(SpaceFile *sfile)
void fileselect_file_set(SpaceFile *sfile, const int index)
{
const struct FileDirEntry *file = filelist_file(sfile->files, index);
- if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_FOLDER)) {
+ if (file && file->relpath && file->relpath[0] && !(file->typeflag & FILE_TYPE_DIR)) {
BLI_strncpy(sfile->params->file, file->relpath, FILE_MAXFILE);
}
}
@@ -372,10 +386,10 @@ int ED_fileselect_layout_numfiles(FileLayout *layout, ARegion *ar)
}
else {
const int y_item = layout->tile_h + (2 * layout->tile_border_y);
- const int y_view = (int)(BLI_rctf_size_y(&ar->v2d.cur));
+ const int y_view = (int)(BLI_rctf_size_y(&ar->v2d.cur)) - layout->offset_top;
const int y_over = y_item - (y_view % y_item);
numfiles = (int)((float)(y_view + y_over) / (float)(y_item));
- return numfiles * layout->columns;
+ return numfiles * layout->flow_columns;
}
}
@@ -395,19 +409,19 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r
}
colmin = (rect->xmin) / (layout->tile_w + 2 * layout->tile_border_x);
- rowmin = (rect->ymin) / (layout->tile_h + 2 * layout->tile_border_y);
+ rowmin = (rect->ymin - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
colmax = (rect->xmax) / (layout->tile_w + 2 * layout->tile_border_x);
- rowmax = (rect->ymax) / (layout->tile_h + 2 * layout->tile_border_y);
+ rowmax = (rect->ymax - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
- if (is_inside(colmin, rowmin, layout->columns, layout->rows) ||
- is_inside(colmax, rowmax, layout->columns, layout->rows)) {
- CLAMP(colmin, 0, layout->columns - 1);
+ if (is_inside(colmin, rowmin, layout->flow_columns, layout->rows) ||
+ is_inside(colmax, rowmax, layout->flow_columns, layout->rows)) {
+ CLAMP(colmin, 0, layout->flow_columns - 1);
CLAMP(rowmin, 0, layout->rows - 1);
- CLAMP(colmax, 0, layout->columns - 1);
+ CLAMP(colmax, 0, layout->flow_columns - 1);
CLAMP(rowmax, 0, layout->rows - 1);
}
- if ((colmin > layout->columns - 1) || (rowmin > layout->rows - 1)) {
+ if ((colmin > layout->flow_columns - 1) || (rowmin > layout->rows - 1)) {
sel.first = -1;
}
else {
@@ -415,10 +429,10 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r
sel.first = layout->rows * colmin + rowmin;
}
else {
- sel.first = colmin + layout->columns * rowmin;
+ sel.first = colmin + layout->flow_columns * rowmin;
}
}
- if ((colmax > layout->columns - 1) || (rowmax > layout->rows - 1)) {
+ if ((colmax > layout->flow_columns - 1) || (rowmax > layout->rows - 1)) {
sel.last = -1;
}
else {
@@ -426,7 +440,7 @@ FileSelection ED_fileselect_layout_offset_rect(FileLayout *layout, const rcti *r
sel.last = layout->rows * colmax + rowmax;
}
else {
- sel.last = colmax + layout->columns * rowmax;
+ sel.last = colmax + layout->flow_columns * rowmax;
}
}
@@ -443,9 +457,9 @@ int ED_fileselect_layout_offset(FileLayout *layout, int x, int y)
}
offsetx = (x) / (layout->tile_w + 2 * layout->tile_border_x);
- offsety = (y) / (layout->tile_h + 2 * layout->tile_border_y);
+ offsety = (y - layout->offset_top) / (layout->tile_h + 2 * layout->tile_border_y);
- if (offsetx > layout->columns - 1) {
+ if (offsetx > layout->flow_columns - 1) {
return -1;
}
if (offsety > layout->rows - 1) {
@@ -456,25 +470,121 @@ int ED_fileselect_layout_offset(FileLayout *layout, int x, int y)
active_file = layout->rows * offsetx + offsety;
}
else {
- active_file = offsetx + layout->columns * offsety;
+ active_file = offsetx + layout->flow_columns * offsety;
}
return active_file;
}
+/**
+ * Get the currently visible bounds of the layout in screen space. Matches View2D.mask minus the
+ * top column-header row.
+ */
+void ED_fileselect_layout_maskrect(const FileLayout *layout, const View2D *v2d, rcti *r_rect)
+{
+ *r_rect = v2d->mask;
+ r_rect->ymax -= layout->offset_top;
+}
+
+bool ED_fileselect_layout_is_inside_pt(const FileLayout *layout, const View2D *v2d, int x, int y)
+{
+ rcti maskrect;
+ ED_fileselect_layout_maskrect(layout, v2d, &maskrect);
+ return BLI_rcti_isect_pt(&maskrect, x, y);
+}
+
+bool ED_fileselect_layout_isect_rect(const FileLayout *layout,
+ const View2D *v2d,
+ const rcti *rect,
+ rcti *r_dst)
+{
+ rcti maskrect;
+ ED_fileselect_layout_maskrect(layout, v2d, &maskrect);
+ return BLI_rcti_isect(&maskrect, rect, r_dst);
+}
+
void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y)
{
if (layout->flag == FILE_LAYOUT_HOR) {
*x = layout->tile_border_x +
(tile / layout->rows) * (layout->tile_w + 2 * layout->tile_border_x);
- *y = layout->tile_border_y +
+ *y = layout->offset_top + layout->tile_border_y +
(tile % layout->rows) * (layout->tile_h + 2 * layout->tile_border_y);
}
else {
*x = layout->tile_border_x +
- ((tile) % layout->columns) * (layout->tile_w + 2 * layout->tile_border_x);
- *y = layout->tile_border_y +
- ((tile) / layout->columns) * (layout->tile_h + 2 * layout->tile_border_y);
+ ((tile) % layout->flow_columns) * (layout->tile_w + 2 * layout->tile_border_x);
+ *y = layout->offset_top + layout->tile_border_y +
+ ((tile) / layout->flow_columns) * (layout->tile_h + 2 * layout->tile_border_y);
+ }
+}
+
+/**
+ * Check if the region coordinate defined by \a x and \a y are inside the column header.
+ */
+bool file_attribute_column_header_is_inside(const View2D *v2d,
+ const FileLayout *layout,
+ int x,
+ int y)
+{
+ rcti header_rect = v2d->mask;
+ header_rect.ymin = header_rect.ymax - layout->attribute_column_header_h;
+ return BLI_rcti_isect_pt(&header_rect, x, y);
+}
+
+bool file_attribute_column_type_enabled(const FileSelectParams *params,
+ FileAttributeColumnType column)
+{
+ switch (column) {
+ case COLUMN_NAME:
+ /* Always enabled */
+ return true;
+ case COLUMN_DATETIME:
+ return (params->details_flags & FILE_DETAILS_DATETIME) != 0;
+ case COLUMN_SIZE:
+ return (params->details_flags & FILE_DETAILS_SIZE) != 0;
+ default:
+ return false;
+ }
+}
+
+/**
+ * Find the column type at region coordinate given by \a x (y doesn't matter for this).
+ */
+FileAttributeColumnType file_attribute_column_type_find_isect(const View2D *v2d,
+ const FileSelectParams *params,
+ FileLayout *layout,
+ int x)
+{
+ float mx, my;
+ int offset_tile;
+
+ UI_view2d_region_to_view(v2d, x, v2d->mask.ymax - layout->offset_top - 1, &mx, &my);
+ offset_tile = ED_fileselect_layout_offset(
+ layout, (int)(v2d->tot.xmin + mx), (int)(v2d->tot.ymax - my));
+ if (offset_tile > -1) {
+ int tile_x, tile_y;
+ int pos_x = 0;
+ int rel_x; /* x relative to the hovered tile */
+
+ ED_fileselect_layout_tilepos(layout, offset_tile, &tile_x, &tile_y);
+ /* Column header drawing doesn't use left tile border, so subtract it. */
+ rel_x = mx - (tile_x - layout->tile_border_x);
+
+ for (FileAttributeColumnType column = 0; column < ATTRIBUTE_COLUMN_MAX; column++) {
+ if (!file_attribute_column_type_enabled(params, column)) {
+ continue;
+ }
+ const int width = layout->attribute_columns[column].width;
+
+ if (IN_RANGE(rel_x, pos_x, pos_x + width)) {
+ return column;
+ }
+
+ pos_x += width;
+ }
}
+
+ return COLUMN_NONE;
}
float file_string_width(const char *str)
@@ -512,20 +622,52 @@ float file_font_pointsize(void)
#endif
}
-static void column_widths(FileSelectParams *params, struct FileLayout *layout)
+static void file_attribute_columns_widths(const FileSelectParams *params, FileLayout *layout)
{
- int i;
+ FileAttributeColumn *columns = layout->attribute_columns;
const bool small_size = SMALL_SIZE_CHECK(params->thumbnail_size);
+ const int pad = small_size ? 0 : ATTRIBUTE_COLUMN_PADDING * 2;
- for (i = 0; i < MAX_FILE_COLUMN; ++i) {
- layout->column_widths[i] = 0;
+ for (int i = 0; i < ATTRIBUTE_COLUMN_MAX; ++i) {
+ layout->attribute_columns[i].width = 0;
}
- layout->column_widths[COLUMN_NAME] = ((float)params->thumbnail_size / 8.0f) * UI_UNIT_X;
/* Biggest possible reasonable values... */
- layout->column_widths[COLUMN_DATE] = file_string_width(small_size ? "23/08/89" : "23-Dec-89");
- layout->column_widths[COLUMN_TIME] = file_string_width("23:59");
- layout->column_widths[COLUMN_SIZE] = file_string_width(small_size ? "98.7 M" : "98.7 MiB");
+ columns[COLUMN_DATETIME].width = file_string_width(small_size ? "23/08/89" :
+ "23 Dec 6789, 23:59") +
+ pad;
+ columns[COLUMN_SIZE].width = file_string_width(small_size ? "98.7 M" : "098.7 MB") + pad;
+ if (params->display == FILE_IMGDISPLAY) {
+ columns[COLUMN_NAME].width = ((float)params->thumbnail_size / 8.0f) * UI_UNIT_X;
+ }
+ /* Name column uses remaining width */
+ else {
+ int remwidth = layout->tile_w;
+ for (FileAttributeColumnType column_type = ATTRIBUTE_COLUMN_MAX - 1; column_type >= 0;
+ column_type--) {
+ if ((column_type == COLUMN_NAME) ||
+ !file_attribute_column_type_enabled(params, column_type)) {
+ continue;
+ }
+ remwidth -= columns[column_type].width;
+ }
+ columns[COLUMN_NAME].width = remwidth;
+ }
+}
+
+static void file_attribute_columns_init(const FileSelectParams *params, FileLayout *layout)
+{
+ file_attribute_columns_widths(params, layout);
+
+ layout->attribute_columns[COLUMN_NAME].name = N_("Name");
+ layout->attribute_columns[COLUMN_NAME].sort_type = FILE_SORT_ALPHA;
+ layout->attribute_columns[COLUMN_NAME].text_align = UI_STYLE_TEXT_LEFT;
+ layout->attribute_columns[COLUMN_DATETIME].name = N_("Date Modified");
+ layout->attribute_columns[COLUMN_DATETIME].sort_type = FILE_SORT_TIME;
+ layout->attribute_columns[COLUMN_DATETIME].text_align = UI_STYLE_TEXT_LEFT;
+ layout->attribute_columns[COLUMN_SIZE].name = N_("Size");
+ layout->attribute_columns[COLUMN_SIZE].sort_type = FILE_SORT_SIZE;
+ layout->attribute_columns[COLUMN_SIZE].text_align = UI_STYLE_TEXT_RIGHT;
}
void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
@@ -533,7 +675,6 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
FileSelectParams *params = ED_fileselect_get_params(sfile);
FileLayout *layout = NULL;
View2D *v2d = &ar->v2d;
- int maxlen = 0;
int numfiles;
int textheight;
@@ -560,57 +701,66 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, ARegion *ar)
layout->tile_w = layout->prv_w + 2 * layout->prv_border_x;
layout->tile_h = layout->prv_h + 2 * layout->prv_border_y + textheight;
layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
- layout->columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x);
- if (layout->columns > 0) {
- layout->rows = numfiles / layout->columns + 1; // XXX dirty, modulo is zero
+ layout->flow_columns = layout->width / (layout->tile_w + 2 * layout->tile_border_x);
+ layout->attribute_column_header_h = 0;
+ layout->offset_top = 0;
+ if (layout->flow_columns > 0) {
+ layout->rows = numfiles / layout->flow_columns + 1; // XXX dirty, modulo is zero
}
else {
- layout->columns = 1;
+ layout->flow_columns = 1;
layout->rows = numfiles + 1; // XXX dirty, modulo is zero
}
layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) +
- layout->tile_border_y * 2;
+ layout->tile_border_y * 2 - layout->offset_top;
layout->flag = FILE_LAYOUT_VER;
}
- else {
- int column_space = 0.6f * UI_UNIT_X;
- int column_icon_space = 0.2f * UI_UNIT_X;
+ else if (params->display == FILE_VERTICALDISPLAY) {
+ int rowcount;
- layout->prv_w = 0;
- layout->prv_h = 0;
+ layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X;
+ layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y;
+ layout->tile_border_x = 0.4f * UI_UNIT_X;
+ layout->tile_border_y = 0.1f * UI_UNIT_Y;
+ layout->tile_h = textheight * 3 / 2;
+ layout->width = (int)(BLI_rctf_size_x(&v2d->cur) - 2 * layout->tile_border_x);
+ layout->tile_w = layout->width;
+ layout->flow_columns = 1;
+ layout->attribute_column_header_h = layout->tile_h * 1.2f + 2 * layout->tile_border_y;
+ layout->offset_top = layout->attribute_column_header_h;
+ rowcount = (int)(BLI_rctf_size_y(&v2d->cur) - layout->offset_top - 2 * layout->tile_border_y) /
+ (layout->tile_h + 2 * layout->tile_border_y);
+ file_attribute_columns_init(params, layout);
+
+ layout->rows = MAX2(rowcount, numfiles);
+ BLI_assert(layout->rows != 0);
+ layout->height = sfile->layout->rows * (layout->tile_h + 2 * layout->tile_border_y) +
+ layout->tile_border_y * 2 + layout->offset_top;
+ layout->flag = FILE_LAYOUT_VER;
+ }
+ else if (params->display == FILE_HORIZONTALDISPLAY) {
+ layout->prv_w = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_X;
+ layout->prv_h = ((float)params->thumbnail_size / 20.0f) * UI_UNIT_Y;
layout->tile_border_x = 0.4f * UI_UNIT_X;
layout->tile_border_y = 0.1f * UI_UNIT_Y;
- layout->prv_border_x = 0;
- layout->prv_border_y = 0;
layout->tile_h = textheight * 3 / 2;
+ layout->attribute_column_header_h = 0;
+ layout->offset_top = layout->attribute_column_header_h;
layout->height = (int)(BLI_rctf_size_y(&v2d->cur) - 2 * layout->tile_border_y);
/* Padding by full scrollbar H is too much, can overlap tile border Y. */
layout->rows = (layout->height - V2D_SCROLL_HEIGHT + layout->tile_border_y) /
(layout->tile_h + 2 * layout->tile_border_y);
+ layout->tile_w = VERTLIST_MAJORCOLUMN_WIDTH;
+ file_attribute_columns_init(params, layout);
- column_widths(params, layout);
-
- if (params->display == FILE_SHORTDISPLAY) {
- maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
- (int)layout->column_widths[COLUMN_NAME] + column_space +
- (int)layout->column_widths[COLUMN_SIZE] + column_space;
- }
- else {
- maxlen = ICON_DEFAULT_WIDTH_SCALE + column_icon_space +
- (int)layout->column_widths[COLUMN_NAME] + column_space +
- (int)layout->column_widths[COLUMN_DATE] + column_space +
- (int)layout->column_widths[COLUMN_TIME] + column_space +
- (int)layout->column_widths[COLUMN_SIZE] + column_space;
- }
- layout->tile_w = maxlen;
if (layout->rows > 0) {
- layout->columns = numfiles / layout->rows + 1; // XXX dirty, modulo is zero
+ layout->flow_columns = numfiles / layout->rows + 1; // XXX dirty, modulo is zero
}
else {
layout->rows = 1;
- layout->columns = numfiles + 1; // XXX dirty, modulo is zero
+ layout->flow_columns = numfiles + 1; // XXX dirty, modulo is zero
}
- layout->width = sfile->layout->columns * (layout->tile_w + 2 * layout->tile_border_x) +
+ layout->width = sfile->layout->flow_columns * (layout->tile_w + 2 * layout->tile_border_x) +
layout->tile_border_x * 2;
layout->flag = FILE_LAYOUT_HOR;
}
diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c
index 1fd878e4662..1befdd52d7d 100644
--- a/source/blender/editors/space_file/space_file.c
+++ b/source/blender/editors/space_file/space_file.c
@@ -72,23 +72,40 @@ static SpaceLink *file_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scen
/* Ignore user preference "USER_HEADER_BOTTOM" here (always show top for new types). */
ar->alignment = RGN_ALIGN_TOP;
+ /* ui list region */
+ ar = MEM_callocN(sizeof(ARegion), "ui region for file");
+ BLI_addtail(&sfile->regionbase, ar);
+ ar->regiontype = RGN_TYPE_UI;
+ ar->alignment = RGN_ALIGN_TOP;
+ ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+
/* Tools region */
ar = MEM_callocN(sizeof(ARegion), "tools region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOLS;
ar->alignment = RGN_ALIGN_LEFT;
+ /* Tools region (lower split region) */
+ ar = MEM_callocN(sizeof(ARegion), "lower tools region for file");
+ BLI_addtail(&sfile->regionbase, ar);
+ ar->regiontype = RGN_TYPE_TOOLS;
+ ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
+ ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+
+ /* Execute region */
+ ar = MEM_callocN(sizeof(ARegion), "execute region for file");
+ BLI_addtail(&sfile->regionbase, ar);
+ ar->regiontype = RGN_TYPE_EXECUTE;
+ ar->alignment = RGN_ALIGN_BOTTOM;
+ ar->flag |= RGN_FLAG_DYNAMIC_SIZE;
+ /* Tool props region is added as needed. */
+#if 0
/* Tool props (aka operator) region */
ar = MEM_callocN(sizeof(ARegion), "tool props region for file");
BLI_addtail(&sfile->regionbase, ar);
ar->regiontype = RGN_TYPE_TOOL_PROPS;
- ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
-
- /* ui list region */
- ar = MEM_callocN(sizeof(ARegion), "ui region for file");
- BLI_addtail(&sfile->regionbase, ar);
- ar->regiontype = RGN_TYPE_UI;
- ar->alignment = RGN_ALIGN_TOP;
+ ar->alignment = RGN_ALIGN_RIGHT;
+#endif
/* main region */
ar = MEM_callocN(sizeof(ARegion), "main region for file");
@@ -204,6 +221,7 @@ static SpaceLink *file_duplicate(SpaceLink *sl)
static void file_refresh(const bContext *C, ScrArea *sa)
{
wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *win = CTX_wm_window(C);
SpaceFile *sfile = CTX_wm_space_file(C);
FileSelectParams *params = ED_fileselect_get_params(sfile);
struct FSMenu *fsmenu = ED_fsmenu_get();
@@ -217,15 +235,16 @@ static void file_refresh(const bContext *C, ScrArea *sa)
}
filelist_setdir(sfile->files, params->dir);
filelist_setrecursion(sfile->files, params->recursion_level);
- filelist_setsorting(sfile->files, params->sort);
- filelist_setfilter_options(sfile->files,
- (params->flag & FILE_FILTER) != 0,
- (params->flag & FILE_HIDE_DOT) != 0,
- false, /* TODO hide_parent, should be controllable? */
- params->filter,
- params->filter_id,
- params->filter_glob,
- params->filter_search);
+ filelist_setsorting(sfile->files, params->sort, params->flag & FILE_SORT_INVERT);
+ filelist_setfilter_options(
+ sfile->files,
+ (params->flag & FILE_FILTER) != 0,
+ (params->flag & FILE_HIDE_DOT) != 0,
+ true, /* Just always hide parent, prefer to not add an extra user option for this. */
+ params->filter,
+ params->filter_id,
+ params->filter_glob,
+ params->filter_search);
/* Update the active indices of bookmarks & co. */
sfile->systemnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM, params->dir);
@@ -254,7 +273,7 @@ static void file_refresh(const bContext *C, ScrArea *sa)
else {
filelist_cache_previews_set(sfile->files, false);
if (sfile->previews_timer) {
- WM_event_remove_timer_notifier(wm, CTX_wm_window(C), sfile->previews_timer);
+ WM_event_remove_timer_notifier(wm, win, sfile->previews_timer);
sfile->previews_timer = NULL;
}
}
@@ -269,10 +288,20 @@ static void file_refresh(const bContext *C, ScrArea *sa)
/* Might be called with NULL sa, see file_main_region_draw() below. */
if (sa && BKE_area_find_region_type(sa, RGN_TYPE_TOOLS) == NULL) {
- /* Create TOOLS/TOOL_PROPS regions. */
+ /* Create TOOLS region. */
file_tools_region(sa);
- ED_area_initialize(wm, CTX_wm_window(C), sa);
+ ED_area_initialize(wm, win, sa);
+ }
+ if (sa && sfile->op && BKE_area_find_region_type(sa, RGN_TYPE_TOOL_PROPS) == NULL) {
+ /* Create TOOL_PROPS region. */
+ ARegion *region_props = file_tool_props_region(sa);
+
+ if (params->flag & FILE_HIDE_TOOL_PROPS) {
+ region_props->flag |= RGN_FLAG_HIDDEN;
+ }
+
+ ED_area_initialize(wm, win, sa);
}
ED_area_tag_redraw(sa);
@@ -406,6 +435,11 @@ static void file_main_region_draw(const bContext *C, ARegion *ar)
v2d->keepofs &= ~V2D_LOCKOFS_Y;
v2d->keepofs |= V2D_LOCKOFS_X;
}
+ else if (params->display == FILE_VERTICALDISPLAY) {
+ v2d->scroll = V2D_SCROLL_RIGHT;
+ v2d->keepofs &= ~V2D_LOCKOFS_Y;
+ v2d->keepofs |= V2D_LOCKOFS_X;
+ }
else {
v2d->scroll = V2D_SCROLL_BOTTOM;
v2d->keepofs &= ~V2D_LOCKOFS_X;
@@ -439,7 +473,9 @@ static void file_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* scrollers */
- scrollers = UI_view2d_scrollers_calc(v2d, NULL);
+ rcti view_rect;
+ ED_fileselect_layout_maskrect(sfile->layout, v2d, &view_rect);
+ scrollers = UI_view2d_scrollers_calc(v2d, &view_rect);
UI_view2d_scrollers_draw(v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
}
@@ -452,6 +488,7 @@ static void file_operatortypes(void)
WM_operatortype_append(FILE_OT_select_box);
WM_operatortype_append(FILE_OT_select_bookmark);
WM_operatortype_append(FILE_OT_highlight);
+ WM_operatortype_append(FILE_OT_sort_column_ui_context);
WM_operatortype_append(FILE_OT_execute);
WM_operatortype_append(FILE_OT_cancel);
WM_operatortype_append(FILE_OT_parent);
@@ -538,7 +575,8 @@ static void file_ui_region_init(wmWindowManager *wm, ARegion *ar)
{
wmKeyMap *keymap;
- UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
+ ED_region_panels_init(wm, ar);
+ ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
/* own keymap */
keymap = WM_keymap_ensure(wm->defaultconf, "File Browser", SPACE_FILE, 0);
@@ -550,22 +588,18 @@ static void file_ui_region_init(wmWindowManager *wm, ARegion *ar)
static void file_ui_region_draw(const bContext *C, ARegion *ar)
{
- float col[3];
- /* clear */
- UI_GetThemeColor3fv(TH_BACK, col);
- GPU_clear_color(col[0], col[1], col[2], 0.0);
- GPU_clear(GPU_COLOR_BIT);
-
- /* scrolling here is just annoying, disable it */
- ar->v2d.cur.ymax = BLI_rctf_size_y(&ar->v2d.cur);
- ar->v2d.cur.ymin = 0;
-
- /* set view2d view matrix for scrolling (without scrollers) */
- UI_view2d_view_ortho(&ar->v2d);
+ ED_region_panels(C, ar);
+}
- file_draw_buttons(C, ar);
+static void file_execution_region_init(wmWindowManager *wm, ARegion *ar)
+{
+ ED_region_panels_init(wm, ar);
+ ar->v2d.keepzoom |= V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y;
+}
- UI_view2d_view_restore(C);
+static void file_execution_region_draw(const bContext *C, ARegion *ar)
+{
+ ED_region_panels(C, ar);
}
static void file_ui_region_listener(wmWindow *UNUSED(win),
@@ -656,13 +690,21 @@ void ED_spacetype_file(void)
/* regions: ui */
art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
art->regionid = RGN_TYPE_UI;
- art->prefsizey = 60;
art->keymapflag = ED_KEYMAP_UI;
art->listener = file_ui_region_listener;
art->init = file_ui_region_init;
art->draw = file_ui_region_draw;
BLI_addhead(&st->regiontypes, art);
+ /* regions: execution */
+ art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
+ art->regionid = RGN_TYPE_EXECUTE;
+ art->keymapflag = ED_KEYMAP_UI;
+ art->listener = file_ui_region_listener;
+ art->init = file_execution_region_init;
+ art->draw = file_execution_region_draw;
+ BLI_addhead(&st->regiontypes, art);
+
/* regions: channels (directories) */
art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
art->regionid = RGN_TYPE_TOOLS;
@@ -677,8 +719,8 @@ void ED_spacetype_file(void)
/* regions: tool properties */
art = MEM_callocN(sizeof(ARegionType), "spacetype file operator region");
art->regionid = RGN_TYPE_TOOL_PROPS;
- art->prefsizex = 0;
- art->prefsizey = 360;
+ art->prefsizex = 240;
+ art->prefsizey = 60;
art->keymapflag = ED_KEYMAP_UI;
art->listener = file_tools_region_listener;
art->init = file_tools_region_init;
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index c727c5225c9..708d91a82bb 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -861,6 +861,11 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar
sub = uiLayoutColumn(layout, true);
uiItemR(sub, &dtar_ptr, "transform_type", 0, NULL, ICON_NONE);
+
+ if (ELEM(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
+ uiItemR(sub, &dtar_ptr, "rotation_mode", 0, IFACE_("Mode"), ICON_NONE);
+ }
+
uiItemR(sub, &dtar_ptr, "transform_space", 0, IFACE_("Space"), ICON_NONE);
}
@@ -1236,7 +1241,7 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *pa)
{
uiLayout *layout = pa->layout;
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop = NULL;
int index = -1;
uiBut *but = NULL;
@@ -1258,7 +1263,7 @@ static void graph_panel_drivers_popover(const bContext *C, Panel *pa)
/* Populate Panel - With a combination of the contents of the Driven and Driver panels */
if (fcu && fcu->driver) {
- ID *id = ptr.id.data;
+ ID *id = ptr.owner_id;
PointerRNA ptr_fcurve;
RNA_pointer_create(id, &RNA_FCurve, fcu, &ptr_fcurve);
diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c
index e7ba498fc11..e18a440f7c0 100644
--- a/source/blender/editors/space_graph/graph_draw.c
+++ b/source/blender/editors/space_graph/graph_draw.c
@@ -205,7 +205,7 @@ static void draw_fcurve_keyframe_vertices(FCurve *fcu, View2D *v2d, bool edit, u
{
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA);
- immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.pixelsize);
+ immUniform1f("size", UI_GetThemeValuef(TH_VERTEX_SIZE) * U.dpi_fac);
draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, false, pos);
draw_fcurve_selected_keyframe_vertices(fcu, v2d, edit, true, pos);
@@ -269,8 +269,8 @@ static void draw_fcurve_handle_vertices(FCurve *fcu,
immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA);
/* set handle size */
- immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.pixelsize);
- immUniform1f("outlineWidth", 1.5f * U.pixelsize);
+ immUniform1f("size", (1.4f * UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE)) * U.dpi_fac);
+ immUniform1f("outlineWidth", 1.5f * U.dpi_fac);
draw_fcurve_selected_handle_vertices(fcu, v2d, false, sel_handle_only, pos);
draw_fcurve_selected_handle_vertices(fcu, v2d, true, sel_handle_only, pos);
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index b624e21937f..329067de545 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -1538,7 +1538,7 @@ void GRAPH_OT_sound_bake(wmOperatorType *ot)
FILE_TYPE_FOLDER | FILE_TYPE_SOUND | FILE_TYPE_MOVIE,
FILE_SPECIAL,
FILE_OPENFILE,
- WM_FILESEL_FILEPATH,
+ WM_FILESEL_FILEPATH | WM_FILESEL_SHOW_PROPS,
FILE_DEFAULTDISPLAY,
FILE_SORT_ALPHA);
RNA_def_float(ot->srna,
diff --git a/source/blender/editors/space_graph/graph_intern.h b/source/blender/editors/space_graph/graph_intern.h
index 168c38b66a4..320240221b5 100644
--- a/source/blender/editors/space_graph/graph_intern.h
+++ b/source/blender/editors/space_graph/graph_intern.h
@@ -26,7 +26,6 @@
struct ARegion;
struct ARegionType;
-struct ScrArea;
struct SpaceGraph;
struct bAnimContext;
struct bAnimListElem;
diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c
index 6c5ebf77bf4..91e5ab61dd9 100644
--- a/source/blender/editors/space_graph/space_graph.c
+++ b/source/blender/editors/space_graph/space_graph.c
@@ -527,7 +527,7 @@ static void graph_region_message_subscribe(const struct bContext *UNUSED(C),
* so just whitelist the entire structs for updates
*/
{
- wmMsgParams_RNA msg_key_params = {{{0}}};
+ wmMsgParams_RNA msg_key_params = {{0}};
StructRNA *type_array[] = {
&RNA_DopeSheet, /* dopesheet filters */
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c
index f1a29a1542d..64e1c02590e 100644
--- a/source/blender/editors/space_image/image_buttons.c
+++ b/source/blender/editors/space_image/image_buttons.c
@@ -991,7 +991,7 @@ void uiTemplateImage(uiLayout *layout,
void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, bool color_management)
{
ImageFormatData *imf = imfptr->data;
- ID *id = imfptr->id.data;
+ ID *id = imfptr->owner_id;
PointerRNA display_settings_ptr;
PropertyRNA *prop;
const int depth_ok = BKE_imtype_valid_depths(imf->imtype);
diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h
index 2c723f45e94..1abb6715fdb 100644
--- a/source/blender/editors/space_image/image_intern.h
+++ b/source/blender/editors/space_image/image_intern.h
@@ -27,7 +27,6 @@
/* internal exports only */
struct ARegion;
struct ARegionType;
-struct ScrArea;
struct SpaceImage;
struct bContext;
struct bNodeTree;
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 05ba82b8bde..e338a450db6 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -1431,7 +1431,7 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
Image *oldima;
oldptr = RNA_property_pointer_get(&ptr, prop);
- oldima = (Image *)oldptr.id.data;
+ oldima = (Image *)oldptr.owner_id;
/* unlikely to fail but better avoid strange crash */
if (oldima && GS(oldima->id.name) == ID_IM) {
ima = oldima;
@@ -1773,6 +1773,7 @@ static int image_save_options_init(Main *bmain,
}
else {
BLI_snprintf(opts->filepath, sizeof(opts->filepath), "//%s", ima->id.name + 2);
+ BLI_path_make_safe(opts->filepath);
BLI_path_abs(opts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain));
}
}
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 33e77d3623e..5fa4fe3e077 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -586,7 +586,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar)
float col[3];
/* XXX This is in order to draw UI batches with the DRW
- * olg context since we now use it for drawing the entire area */
+ * old context since we now use it for drawing the entire area. */
gpu_batch_presets_reset();
GPUViewport *viewport =
diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c
index 946274de882..106edc290d5 100644
--- a/source/blender/editors/space_info/info_stats.c
+++ b/source/blender/editors/space_info/info_stats.c
@@ -574,7 +574,7 @@ void ED_info_stats_clear(ViewLayer *view_layer)
const char *ED_info_stats_string(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
- /* Loopin through dependency graph when interface is locked in not safe.
+ /* Looping through dependency graph when interface is locked in not safe.
* Thew interface is marked as locked when jobs wants to modify the
* dependency graph. */
wmWindowManager *wm = bmain->wm.first;
diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c
index 24d3008b1e7..97d5faa9c13 100644
--- a/source/blender/editors/space_info/textview.c
+++ b/source/blender/editors/space_info/textview.c
@@ -313,7 +313,7 @@ int textview_draw(
/* constants for the sequencer context */
cdc.font_id = font_id;
cdc.cwidth = (int)BLF_fixed_width(font_id);
- assert(cdc.cwidth > 0);
+ BLI_assert(cdc.cwidth > 0);
cdc.lheight = tvc->lheight;
cdc.lofs = -BLF_descender(font_id);
/* note, scroll bar must be already subtracted () */
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 719efc7eeac..126b20a028e 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -268,8 +268,8 @@ static void nla_panel_animdata(const bContext *C, Panel *pa)
/* icon + id-block name of block where AnimData came from to prevent
* accidentally changing the properties of the wrong action
*/
- if (adt_ptr.id.data) {
- ID *id = adt_ptr.id.data;
+ if (adt_ptr.owner_id) {
+ ID *id = adt_ptr.owner_id;
PointerRNA id_ptr;
RNA_id_pointer_create(id, &id_ptr);
@@ -513,7 +513,7 @@ static void nla_panel_modifiers(const bContext *C, Panel *pa)
for (fcm = strip->modifiers.first; fcm; fcm = fcm->next) {
col = uiLayoutColumn(pa->layout, true);
- ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.id.data, &strip->modifiers, fcm);
+ ANIM_uiTemplate_fmodifier_draw(col, strip_ptr.owner_id, &strip->modifiers, fcm);
}
}
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index e5c116e85de..456eb783706 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -446,7 +446,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
/* get anim-channel to use (or more specifically, the animdata block behind it) */
if (channel_index == -1) {
- PointerRNA adt_ptr = {{NULL}};
+ PointerRNA adt_ptr = {NULL};
/* active animdata block */
if (nla_panel_context(C, &adt_ptr, NULL, NULL) == 0 || (adt_ptr.data == NULL)) {
@@ -458,7 +458,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
else {
- id = adt_ptr.id.data;
+ id = adt_ptr.owner_id;
adt = adt_ptr.data;
}
}
@@ -581,7 +581,7 @@ static int nla_action_unlink_exec(bContext *C, wmOperator *op)
/* do unlinking */
if (adt && adt->action) {
bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
- ED_animedit_unlink_action(C, adt_ptr.id.data, adt, adt->action, op->reports, force_delete);
+ ED_animedit_unlink_action(C, adt_ptr.owner_id, adt, adt->action, op->reports, force_delete);
}
return OPERATOR_FINISHED;
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index 5cf9646210e..9d6ccd6fe35 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -141,8 +141,10 @@ static void nla_action_draw_keyframes(
uint outline_color_id = GPU_vertformat_attr_add(
format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
- immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+
GPU_program_point_size(true);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ immUniform1f("outline_scale", 1.0f);
immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
immBegin(GPU_PRIM_POINTS, key_len);
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 3bdd2804efc..f274f3c93ec 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -522,7 +522,7 @@ static void nla_channel_region_message_subscribe(const struct bContext *UNUSED(C
* so just whitelist the entire struct for updates
*/
{
- wmMsgParams_RNA msg_key_params = {{{0}}};
+ wmMsgParams_RNA msg_key_params = {{0}};
StructRNA *type_array[] = {
&RNA_DopeSheet,
};
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 748e485f614..b89f163f579 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -24,6 +24,7 @@
#include "BLI_blenlib.h"
#include "BLI_math.h"
+#include "BLI_system.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
@@ -90,7 +91,7 @@ static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *p
/* first output stores value */
bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
- RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr);
uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
}
@@ -102,7 +103,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr
bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
uiLayout *col;
- RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr);
col = uiLayoutColumn(layout, false);
uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0);
@@ -113,7 +114,7 @@ static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA
{
uiLayout *row, *col;
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
col = uiLayoutColumn(layout, false);
row = uiLayoutRow(col, true);
@@ -193,7 +194,7 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *
/* first output stores normal */
bNodeSocket *output = node->outputs.first;
PointerRNA sockptr;
- RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, output, &sockptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr);
uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
}
@@ -1186,6 +1187,11 @@ static void node_shader_buts_ambient_occlusion(uiLayout *layout,
uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE);
}
+static void node_shader_buts_white_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+ uiItemR(layout, ptr, "dimensions", 0, "", ICON_NONE);
+}
+
/* only once called */
static void node_shader_set_butfunc(bNodeType *ntype)
{
@@ -1220,7 +1226,7 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_MATH:
ntype->draw_buttons = node_buts_math;
break;
- case SH_NODE_VECT_MATH:
+ case SH_NODE_VECTOR_MATH:
ntype->draw_buttons = node_shader_buts_vect_math;
break;
case SH_NODE_VECT_TRANSFORM:
@@ -1330,6 +1336,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
case SH_NODE_AMBIENT_OCCLUSION:
ntype->draw_buttons = node_shader_buts_ambient_occlusion;
break;
+ case SH_NODE_TEX_WHITE_NOISE:
+ ntype->draw_buttons = node_shader_buts_white_noise;
+ break;
}
}
@@ -1363,7 +1372,7 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
bNode *node = ptr->data;
PointerRNA imaptr, iuserptr;
- RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_ImageUser, node->storage, &iuserptr);
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(layout,
C,
@@ -1390,7 +1399,7 @@ static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRN
bNode *node = ptr->data;
PointerRNA iuserptr;
- RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_ImageUser, node->storage, &iuserptr);
uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 1);
}
@@ -1951,7 +1960,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi
}
/* XXX collection lookup does not return the ID part of the pointer,
* setting this manually here */
- active_input_ptr.id.data = ptr->id.data;
+ active_input_ptr.owner_id = ptr->owner_id;
col = uiLayoutColumn(row, true);
ot = WM_operatortype_find("NODE_OT_output_file_move_active_socket", false);
@@ -2695,6 +2704,10 @@ static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), Po
{
#ifndef WITH_OPENIMAGEDENOISE
uiItemL(layout, IFACE_("Disabled, built without OpenImageDenoise"), ICON_ERROR);
+#else
+ if (!BLI_cpu_support_sse41()) {
+ uiItemL(layout, IFACE_("Disabled, CPU with SSE4.1 is required"), ICON_ERROR);
+ }
#endif
uiItemR(layout, ptr, "use_hdr", 0, NULL, ICON_NONE);
@@ -2959,7 +2972,7 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe
{
PointerRNA tex_ptr;
bNode *node = ptr->data;
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
Tex *tex = (Tex *)node->storage;
uiLayout *col, *row;
@@ -3053,7 +3066,7 @@ static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA
bNode *node = ptr->data;
PointerRNA iuserptr;
- RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_ImageUser, node->storage, &iuserptr);
uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0);
}
@@ -3115,7 +3128,7 @@ static void node_texture_set_butfunc(bNodeType *ntype)
static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = ptr->data;
ED_node_tag_update_nodetree(bmain, ntree, node);
}
@@ -3285,7 +3298,7 @@ static void node_file_output_socket_draw(bContext *C,
PointerRNA *ptr,
PointerRNA *node_ptr)
{
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = ptr->data;
uiLayout *row;
PointerRNA inputptr, imfptr;
@@ -3358,8 +3371,13 @@ static void std_node_socket_draw(
uiTemplateComponentMenu(layout, ptr, "default_value", text);
}
else {
- uiLayout *column = uiLayoutColumn(layout, true);
- uiItemR(column, ptr, "default_value", 0, text, 0);
+ if (sock->typeinfo->subtype == PROP_DIRECTION) {
+ uiItemR(layout, ptr, "default_value", 0, "", ICON_NONE);
+ }
+ else {
+ uiLayout *column = uiLayoutColumn(layout, true);
+ uiItemR(column, ptr, "default_value", 0, text, ICON_NONE);
+ }
}
break;
case SOCK_RGBA:
diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c
index 1c3544077c4..6dc2182b684 100644
--- a/source/blender/editors/space_node/node_draw.c
+++ b/source/blender/editors/space_node/node_draw.c
@@ -713,15 +713,28 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
GPU_blend(false);
}
-static void node_socket_circle_draw(const bContext *C,
- bNodeTree *ntree,
- PointerRNA node_ptr,
- bNodeSocket *sock,
- unsigned pos,
- unsigned col)
+/* flags used in gpu_shader_keyframe_diamond_frag.glsl */
+#define MARKER_SHAPE_DIAMOND 0x1
+#define MARKER_SHAPE_SQUARE 0xC
+#define MARKER_SHAPE_CIRCLE 0x2
+#define MARKER_SHAPE_INNER_DOT 0x10
+
+static void node_socket_draw(const bContext *C,
+ bNodeTree *ntree,
+ PointerRNA node_ptr,
+ bNodeSocket *sock,
+ unsigned pos_id,
+ unsigned col_id,
+ unsigned shape_id,
+ unsigned size_id,
+ unsigned outline_col_id,
+ float size,
+ bool selected)
{
PointerRNA ptr;
float color[4];
+ float outline_color[4];
+ unsigned int flags = 0;
RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color);
@@ -731,8 +744,44 @@ static void node_socket_circle_draw(const bContext *C,
color[3] *= 0.25f;
}
- immAttr4fv(col, color);
- immVertex2f(pos, sock->locx, sock->locy);
+ if (selected) {
+ UI_GetThemeColor4fv(TH_TEXT_HI, outline_color);
+ outline_color[3] = 0.9f;
+ }
+ else {
+ copy_v4_fl(outline_color, 0.0f);
+ outline_color[3] = 0.6f;
+ }
+
+ /* sets shape flags */
+ switch (sock->display_shape) {
+ case SOCK_DISPLAY_SHAPE_DIAMOND:
+ case SOCK_DISPLAY_SHAPE_DIAMOND_DOT:
+ flags = MARKER_SHAPE_DIAMOND;
+ break;
+ case SOCK_DISPLAY_SHAPE_SQUARE:
+ case SOCK_DISPLAY_SHAPE_SQUARE_DOT:
+ flags = MARKER_SHAPE_SQUARE;
+ break;
+ default:
+ case SOCK_DISPLAY_SHAPE_CIRCLE:
+ case SOCK_DISPLAY_SHAPE_CIRCLE_DOT:
+ flags = MARKER_SHAPE_CIRCLE;
+ break;
+ }
+
+ if (ELEM(sock->display_shape,
+ SOCK_DISPLAY_SHAPE_DIAMOND_DOT,
+ SOCK_DISPLAY_SHAPE_SQUARE_DOT,
+ SOCK_DISPLAY_SHAPE_CIRCLE_DOT)) {
+ flags |= MARKER_SHAPE_INNER_DOT;
+ }
+
+ immAttr4fv(col_id, color);
+ immAttr1u(shape_id, flags);
+ immAttr1f(size_id, size);
+ immAttr4fv(outline_col_id, outline_color);
+ immVertex2f(pos_id, sock->locx, sock->locy);
}
/* ************** Socket callbacks *********** */
@@ -888,26 +937,28 @@ void node_draw_sockets(View2D *v2d,
PointerRNA node_ptr;
RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr);
- float scale;
- UI_view2d_scale_get(v2d, &scale, NULL);
+ bool selected = false;
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);
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+ uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint outline_col_id = GPU_vertformat_attr_add(
+ format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
GPU_blend(true);
GPU_program_point_size(true);
-
- immBindBuiltinProgram(GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ immUniform1f("outline_scale", 0.7f);
+ immUniform2f("ViewportSize", -1.0f, -1.0f);
/* set handle size */
- immUniform1f("size", 2.0f * NODE_SOCKSIZE * scale); /* 2 * size to have diameter */
+ float scale;
+ UI_view2d_scale_get(v2d, &scale, NULL);
+ scale *= 2.25f * NODE_SOCKSIZE;
if (!select_all) {
- /* outline for unselected sockets */
- immUniform1f("outlineWidth", 1.0f);
- immUniform4f("outlineColor", 0.0f, 0.0f, 0.0f, 0.6f);
-
immBeginAtMost(GPU_PRIM_POINTS, total_input_len + total_output_len);
}
@@ -923,7 +974,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
- node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ node_socket_draw(C,
+ ntree,
+ node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
}
/* socket outputs */
@@ -938,7 +999,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
- node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ node_socket_draw(C,
+ ntree,
+ node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
}
}
@@ -949,10 +1020,8 @@ void node_draw_sockets(View2D *v2d,
/* go back and draw selected sockets */
if (selected_input_len + selected_output_len > 0) {
/* outline for selected sockets */
- float c[3];
- UI_GetThemeColor3fv(TH_TEXT_HI, c);
- immUniform4f("outlineColor", c[0], c[1], c[2], 1.0f);
- immUniform1f("outlineWidth", 1.5f);
+
+ selected = true;
immBegin(GPU_PRIM_POINTS, selected_input_len + selected_output_len);
@@ -963,7 +1032,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
if (select_all || (sock->flag & SELECT)) {
- node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ node_socket_draw(C,
+ ntree,
+ node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
if (--selected_input_len == 0) {
break; /* stop as soon as last one is drawn */
}
@@ -978,7 +1057,17 @@ void node_draw_sockets(View2D *v2d,
continue;
}
if (select_all || (sock->flag & SELECT)) {
- node_socket_circle_draw(C, ntree, node_ptr, sock, pos, col);
+ node_socket_draw(C,
+ ntree,
+ node_ptr,
+ sock,
+ pos_id,
+ col_id,
+ shape_id,
+ size_id,
+ outline_col_id,
+ scale,
+ selected);
if (--selected_output_len == 0) {
break; /* stop as soon as last one is drawn */
}
diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c
index d31256a1425..dcf901216f5 100644
--- a/source/blender/editors/space_node/node_edit.c
+++ b/source/blender/editors/space_node/node_edit.c
@@ -1838,7 +1838,7 @@ static int node_output_file_add_socket_exec(bContext *C, wmOperator *op)
if (ptr.data) {
node = ptr.data;
- ntree = ptr.id.data;
+ ntree = (bNodeTree *)ptr.owner_id;
}
else if (snode && snode->edittree) {
ntree = snode->edittree;
@@ -1886,7 +1886,7 @@ static int node_output_file_remove_active_socket_exec(bContext *C, wmOperator *U
if (ptr.data) {
node = ptr.data;
- ntree = ptr.id.data;
+ ntree = (bNodeTree *)ptr.owner_id;
}
else if (snode && snode->edittree) {
ntree = snode->edittree;
@@ -2535,7 +2535,7 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op)
/* get node */
if (nodeptr.data) {
- ntree_base = nodeptr.id.data;
+ ntree_base = (bNodeTree *)nodeptr.owner_id;
node = nodeptr.data;
}
else if (snode && snode->edittree) {
@@ -2734,7 +2734,7 @@ static int node_cryptomatte_add_socket_exec(bContext *C, wmOperator *UNUSED(op))
if (ptr.data) {
node = ptr.data;
- ntree = ptr.id.data;
+ ntree = (bNodeTree *)ptr.owner_id;
}
else if (snode && snode->edittree) {
ntree = snode->edittree;
@@ -2778,7 +2778,7 @@ static int node_cryptomatte_remove_socket_exec(bContext *C, wmOperator *UNUSED(o
if (ptr.data) {
node = ptr.data;
- ntree = ptr.id.data;
+ ntree = (bNodeTree *)ptr.owner_id;
}
else if (snode && snode->edittree) {
ntree = snode->edittree;
diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c
index 78f36719880..450cf28cce1 100644
--- a/source/blender/editors/space_node/node_select.c
+++ b/source/blender/editors/space_node/node_select.c
@@ -1234,8 +1234,18 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
- but = uiDefSearchBut(
- block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, 9 * UI_UNIT_X, UI_UNIT_Y, 0, 0, "");
+ but = uiDefSearchBut(block,
+ search,
+ 0,
+ ICON_VIEWZOOM,
+ sizeof(search),
+ 10,
+ 10,
+ UI_searchbox_size_x(),
+ UI_UNIT_Y,
+ 0,
+ 0,
+ "");
UI_but_func_search_set(but, NULL, node_find_cb, op->type, false, node_find_call_cb, NULL);
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
@@ -1256,7 +1266,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op)
NULL);
/* Move it downwards, mouse over button. */
- UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y});
+ UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, (const int[2]){0, -UI_UNIT_Y});
return block;
}
diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c
index 8cc57a82fe0..423dec13c69 100644
--- a/source/blender/editors/space_node/node_templates.c
+++ b/source/blender/editors/space_node/node_templates.c
@@ -441,7 +441,7 @@ static int ui_node_item_name_compare(const void *a, const void *b)
{
const bNodeType *type_a = *(const bNodeType **)a;
const bNodeType *type_b = *(const bNodeType **)b;
- return BLI_natstrcmp(type_a->ui_name, type_b->ui_name);
+ return BLI_strcasecmp_natural(type_a->ui_name, type_b->ui_name);
}
static bool ui_node_item_special_poll(const bNodeTree *UNUSED(ntree), const bNodeType *ntype)
diff --git a/source/blender/editors/space_outliner/CMakeLists.txt b/source/blender/editors/space_outliner/CMakeLists.txt
index d235dd47136..616915dbc2c 100644
--- a/source/blender/editors/space_outliner/CMakeLists.txt
+++ b/source/blender/editors/space_outliner/CMakeLists.txt
@@ -41,6 +41,7 @@ set(SRC
outliner_edit.c
outliner_ops.c
outliner_select.c
+ outliner_sync.c
outliner_tools.c
outliner_tree.c
outliner_utils.c
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index 4740c412083..309446db83b 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -89,7 +89,7 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te)
}
else if (ELEM(tselem->type, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
Scene *scene = (Scene *)tselem->id;
- return BKE_collection_master(scene);
+ return scene->master_collection;
}
else if (tselem->type == 0 && te->idcode == ID_GR) {
return (Collection *)tselem->id;
@@ -199,7 +199,7 @@ static int collection_new_exec(bContext *C, wmOperator *op)
}
if (data.collection == NULL || ID_IS_LINKED(data.collection)) {
- data.collection = BKE_collection_master(scene);
+ data.collection = scene->master_collection;
}
if (ID_IS_LINKED(scene)) {
@@ -514,14 +514,14 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op)
* This can happen when a whole scene is linked e.g. */
if (parent != NULL && ID_IS_LINKED(parent)) {
Scene *scene = CTX_data_scene(C);
- parent = ID_IS_LINKED(scene) ? NULL : BKE_collection_master(scene);
+ parent = ID_IS_LINKED(scene) ? NULL : scene->master_collection;
}
else if (parent != NULL && (parent->flag & COLLECTION_IS_MASTER) != 0) {
Scene *scene = BKE_collection_master_scene_search(bmain, parent);
BLI_assert(scene != NULL);
if (ID_IS_LINKED(scene)) {
scene = CTX_data_scene(C);
- parent = ID_IS_LINKED(scene) ? NULL : BKE_collection_master(scene);
+ parent = ID_IS_LINKED(scene) ? NULL : scene->master_collection;
}
}
diff --git a/source/blender/editors/space_outliner/outliner_dragdrop.c b/source/blender/editors/space_outliner/outliner_dragdrop.c
index d8276aa2bbc..6e30157d216 100644
--- a/source/blender/editors/space_outliner/outliner_dragdrop.c
+++ b/source/blender/editors/space_outliner/outliner_dragdrop.c
@@ -326,38 +326,57 @@ static bool parent_drop_poll(bContext *C,
return false;
}
-static int parent_drop_exec(bContext *C, wmOperator *op)
+static void parent_drop_set_parents(
+ bContext *C, ReportList *reports, wmDragID *drag, Object *parent, short parent_type)
{
- Object *par = NULL, *ob = NULL;
Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- int partype = -1;
- char parname[MAX_NAME], childname[MAX_NAME];
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
- 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);
+ TreeElement *te = outliner_find_id(soops, &soops->tree, &parent->id);
+ Scene *scene = (Scene *)outliner_search_back(soops, te, ID_SCE);
- if (ID_IS_LINKED(ob)) {
- BKE_report(op->reports, RPT_INFO, "Can't edit library linked object");
- return OPERATOR_CANCELLED;
+ if (scene == NULL) {
+ /* 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)
+ */
+
+ scene = CTX_data_scene(C);
}
- ED_object_parent_set(op->reports, C, scene, ob, par, partype, false, false, NULL);
+ bool parent_set = false;
+ bool linked_objects = false;
- 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);
+ for (wmDragID *drag_id = drag; drag_id; drag_id = drag_id->next) {
+ if (GS(drag_id->id->name) == ID_OB) {
+ Object *object = (Object *)drag_id->id;
- return OPERATOR_FINISHED;
+ /* Do nothing to linked data */
+ if (ID_IS_LINKED(object)) {
+ linked_objects = true;
+ continue;
+ }
+
+ if (ED_object_parent_set(
+ reports, C, scene, object, parent, parent_type, false, false, NULL)) {
+ parent_set = true;
+ }
+ }
+ }
+
+ if (linked_objects) {
+ BKE_report(reports, RPT_INFO, "Can't edit library linked object(s)");
+ }
+
+ if (parent_set) {
+ 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);
+ }
}
static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
- Main *bmain = CTX_data_main(C);
- SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te = outliner_drop_find(C, event);
TreeStoreElem *tselem = te ? TREESTORE(te) : NULL;
@@ -374,107 +393,15 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event)
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_NAME];
- char parname[MAX_NAME];
- STRNCPY(childname, ob->id.name + 2);
- STRNCPY(parname, par->id.name + 2);
- 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 (event->custom != EVT_DATA_DRAGDROP) {
+ return OPERATOR_CANCELLED;
}
- 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);
+ ListBase *lb = event->customdata;
+ wmDrag *drag = lb->first;
- return OPERATOR_INTERFACE;
- }
+ parent_drop_set_parents(C, op->reports, drag->ids.first, par, PAR_OBJECT);
return OPERATOR_FINISHED;
}
@@ -488,17 +415,11 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot)
/* 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_NAME, "Child", "Child Object");
- RNA_def_string(ot->srna, "parent", "Object", MAX_NAME, "Parent", "Parent Object");
- RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", "");
}
/* ******************** Parent Clear Operator *********************** */
@@ -549,13 +470,21 @@ static bool parent_clear_poll(bContext *C,
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) {
+ if (event->custom != EVT_DATA_DRAGDROP) {
return OPERATOR_CANCELLED;
}
- ED_object_parent_clear(ob, 0);
+ ListBase *lb = event->customdata;
+ wmDrag *drag = lb->first;
+
+ for (wmDragID *drag_id = drag->ids.first; drag_id; drag_id = drag_id->next) {
+ if (GS(drag_id->id->name) == ID_OB) {
+ Object *object = (Object *)drag_id->id;
+
+ ED_object_parent_clear(object, 0);
+ }
+ }
DEG_relations_tag_update(bmain);
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
@@ -608,7 +537,7 @@ static int scene_drop_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent
Collection *collection;
if (scene != CTX_data_scene(C)) {
/* when linking to an inactive scene link to the master collection */
- collection = BKE_collection_master(scene);
+ collection = scene->master_collection;
}
else {
collection = CTX_data_collection(C);
@@ -966,6 +895,12 @@ static int outliner_item_drag_drop_invoke(bContext *C,
return (OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH);
}
+ float view_mval[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+ if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
+ 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 (ELEM(GS(data.drag_id->name), ID_OB, ID_GR)) {
@@ -1032,7 +967,7 @@ static int outliner_item_drag_drop_invoke(bContext *C,
}
else {
Scene *scene = CTX_data_scene(C);
- parent = BKE_collection_master(scene);
+ parent = scene->master_collection;
}
WM_drag_add_ID(drag, id, &parent->id);
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index e4881a6f13d..a2ca3254b30 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -31,6 +31,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_object_force_types.h"
#include "BLI_math.h"
@@ -60,6 +61,7 @@
#include "ED_armature.h"
#include "ED_keyframing.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "WM_api.h"
@@ -175,8 +177,9 @@ static void restrictbutton_r_lay_cb(bContext *C, void *poin, void *UNUSED(poin2)
WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, poin);
}
-static void restrictbutton_bone_visibility_cb(bContext *C, void *UNUSED(poin), void *poin2)
+static void restrictbutton_bone_visibility_cb(bContext *C, void *poin, void *poin2)
{
+ bArmature *arm = (bArmature *)poin;
Bone *bone = (Bone *)poin2;
if (bone->flag & BONE_HIDDEN_P) {
bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
@@ -187,6 +190,7 @@ static void restrictbutton_bone_visibility_cb(bContext *C, void *UNUSED(poin), v
}
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL);
+ DEG_id_tag_update(&arm->id, ID_RECALC_COPY_ON_WRITE);
}
static void restrictbutton_bone_select_cb(bContext *C, void *UNUSED(poin), void *poin2)
@@ -848,6 +852,7 @@ typedef struct RestrictProperties {
PropertyRNA *layer_collection_holdout, *layer_collection_indirect_only,
*layer_collection_hide_viewport;
PropertyRNA *modifier_show_viewport, *modifier_show_render;
+ PropertyRNA *constraint_enable;
} RestrictProperties;
/* We don't care about the value of the property
@@ -865,6 +870,7 @@ typedef struct RestrictPropertiesActive {
bool layer_collection_hide_viewport;
bool modifier_show_viewport;
bool modifier_show_render;
+ bool constraint_enable;
} RestrictPropertiesActive;
static void outliner_restrict_properties_enable_collection_set(
@@ -878,6 +884,7 @@ static void outliner_restrict_properties_enable_collection_set(
props_active->layer_collection_indirect_only = false;
props_active->object_hide_render = false;
props_active->modifier_show_render = false;
+ props_active->constraint_enable = false;
}
}
@@ -891,6 +898,7 @@ static void outliner_restrict_properties_enable_collection_set(
props_active->object_hide_viewport = false;
props_active->base_hide_viewport = false;
props_active->modifier_show_viewport = false;
+ props_active->constraint_enable = false;
}
}
@@ -995,6 +1003,8 @@ static void outliner_draw_restrictbuts(uiBlock *block,
props.modifier_show_viewport = RNA_struct_type_find_property(&RNA_Modifier, "show_viewport");
props.modifier_show_render = RNA_struct_type_find_property(&RNA_Modifier, "show_render");
+ props.constraint_enable = RNA_struct_type_find_property(&RNA_Constraint, "mute");
+
props.initialized = true;
}
@@ -1181,6 +1191,35 @@ static void outliner_draw_restrictbuts(uiBlock *block,
}
}
}
+ else if (tselem->type == TSE_CONSTRAINT) {
+ bConstraint *con = (bConstraint *)te->directdata;
+
+ PointerRNA ptr;
+ RNA_pointer_create(tselem->id, &RNA_Constraint, con, &ptr);
+
+ if (soops->show_restrict_flags & SO_RESTRICT_HIDE) {
+ bt = uiDefIconButR_prop(block,
+ UI_BTYPE_ICON_TOGGLE,
+ 0,
+ 0,
+ (int)(ar->v2d.cur.xmax - restrict_offsets.hide),
+ te->ys,
+ UI_UNIT_X,
+ UI_UNIT_Y,
+ &ptr,
+ props.constraint_enable,
+ -1,
+ 0,
+ 0,
+ -1,
+ -1,
+ NULL);
+ UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
+ if (!props_active.constraint_enable) {
+ UI_but_flag_enable(bt, UI_BUT_INACTIVE);
+ }
+ }
+ }
else if (tselem->type == TSE_MODIFIER) {
ModifierData *md = (ModifierData *)te->directdata;
@@ -1243,7 +1282,7 @@ static void outliner_draw_restrictbuts(uiBlock *block,
UI_BTYPE_ICON_TOGGLE,
BONE_HIDDEN_P,
0,
- ICON_HIDE_OFF,
+ ICON_RESTRICT_VIEW_OFF,
(int)(ar->v2d.cur.xmax - restrict_offsets.viewport),
te->ys,
UI_UNIT_X,
@@ -1878,6 +1917,9 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case TSE_DEFGROUP_BASE:
data.icon = ICON_GROUP_VERTEX;
break;
+ case TSE_DEFGROUP:
+ data.icon = ICON_GROUP_VERTEX;
+ break;
case TSE_BONE:
case TSE_EBONE:
data.icon = ICON_BONE_DATA;
@@ -1885,6 +1927,100 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
case TSE_CONSTRAINT_BASE:
data.icon = ICON_CONSTRAINT;
break;
+ case TSE_CONSTRAINT: {
+ bConstraint *con = te->directdata;
+ switch ((eBConstraint_Types)con->type) {
+ case CONSTRAINT_TYPE_CAMERASOLVER:
+ data.icon = ICON_CON_CAMERASOLVER;
+ break;
+ case CONSTRAINT_TYPE_FOLLOWTRACK:
+ data.icon = ICON_CON_FOLLOWTRACK;
+ break;
+ case CONSTRAINT_TYPE_OBJECTSOLVER:
+ data.icon = ICON_CON_OBJECTSOLVER;
+ break;
+ case CONSTRAINT_TYPE_LOCLIKE:
+ data.icon = ICON_CON_LOCLIKE;
+ break;
+ case CONSTRAINT_TYPE_ROTLIKE:
+ data.icon = ICON_CON_ROTLIKE;
+ break;
+ case CONSTRAINT_TYPE_SIZELIKE:
+ data.icon = ICON_CON_SIZELIKE;
+ break;
+ case CONSTRAINT_TYPE_TRANSLIKE:
+ data.icon = ICON_CON_TRANSLIKE;
+ break;
+ case CONSTRAINT_TYPE_DISTLIMIT:
+ data.icon = ICON_CON_DISTLIMIT;
+ break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ data.icon = ICON_CON_LOCLIMIT;
+ break;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ data.icon = ICON_CON_ROTLIMIT;
+ break;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ data.icon = ICON_CON_SIZELIMIT;
+ break;
+ case CONSTRAINT_TYPE_SAMEVOL:
+ data.icon = ICON_CON_SAMEVOL;
+ break;
+ case CONSTRAINT_TYPE_TRANSFORM:
+ data.icon = ICON_CON_TRANSFORM;
+ break;
+ case CONSTRAINT_TYPE_TRANSFORM_CACHE:
+ data.icon = ICON_CON_TRANSFORM_CACHE;
+ break;
+ case CONSTRAINT_TYPE_CLAMPTO:
+ data.icon = ICON_CON_CLAMPTO;
+ break;
+ case CONSTRAINT_TYPE_DAMPTRACK:
+ data.icon = ICON_CON_TRACKTO;
+ break;
+ case CONSTRAINT_TYPE_KINEMATIC:
+ data.icon = ICON_CON_KINEMATIC;
+ break;
+ case CONSTRAINT_TYPE_LOCKTRACK:
+ data.icon = ICON_CON_LOCKTRACK;
+ break;
+ case CONSTRAINT_TYPE_SPLINEIK:
+ data.icon = ICON_CON_SPLINEIK;
+ break;
+ case CONSTRAINT_TYPE_STRETCHTO:
+ data.icon = ICON_CON_STRETCHTO;
+ break;
+ case CONSTRAINT_TYPE_TRACKTO:
+ data.icon = ICON_CON_TRACKTO;
+ break;
+ case CONSTRAINT_TYPE_ACTION:
+ data.icon = ICON_CON_ACTION;
+ break;
+ case CONSTRAINT_TYPE_ARMATURE:
+ data.icon = ICON_CON_ARMATURE;
+ break;
+ case CONSTRAINT_TYPE_CHILDOF:
+ data.icon = ICON_CON_CHILDOF;
+ break;
+ case CONSTRAINT_TYPE_MINMAX:
+ data.icon = ICON_CON_FLOOR;
+ break;
+ case CONSTRAINT_TYPE_FOLLOWPATH:
+ data.icon = ICON_CON_FOLLOWPATH;
+ break;
+ case CONSTRAINT_TYPE_PIVOT:
+ data.icon = ICON_CON_PIVOT;
+ break;
+ case CONSTRAINT_TYPE_SHRINKWRAP:
+ data.icon = ICON_CON_SHRINKWRAP;
+ break;
+
+ default:
+ data.icon = ICON_DOT;
+ break;
+ }
+ break;
+ }
case TSE_MODIFIER_BASE:
data.icon = ICON_MODIFIER_DATA;
break;
@@ -2137,30 +2273,64 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te)
data.icon = ICON_GROUP_BONE;
break;
case TSE_SEQUENCE:
- if (te->idcode == SEQ_TYPE_MOVIE) {
- data.icon = ICON_SEQUENCE;
- }
- else if (te->idcode == SEQ_TYPE_META) {
- data.icon = ICON_DOT;
- }
- else if (te->idcode == SEQ_TYPE_SCENE) {
- data.icon = ICON_SCENE;
- }
- else if (te->idcode == SEQ_TYPE_SOUND_RAM) {
- data.icon = ICON_SOUND;
- }
- else if (te->idcode == SEQ_TYPE_IMAGE) {
- data.icon = ICON_IMAGE;
- }
- else {
- data.icon = ICON_PARTICLES;
+ switch (te->idcode) {
+ case SEQ_TYPE_SCENE:
+ data.icon = ICON_SCENE_DATA;
+ break;
+ case SEQ_TYPE_MOVIECLIP:
+ data.icon = ICON_TRACKER;
+ break;
+ case SEQ_TYPE_MASK:
+ data.icon = ICON_MOD_MASK;
+ break;
+ case SEQ_TYPE_MOVIE:
+ data.icon = ICON_FILE_MOVIE;
+ break;
+ case SEQ_TYPE_SOUND_RAM:
+ data.icon = ICON_SOUND;
+ break;
+ case SEQ_TYPE_IMAGE:
+ data.icon = ICON_FILE_IMAGE;
+ break;
+ case SEQ_TYPE_COLOR:
+ case SEQ_TYPE_ADJUSTMENT:
+ data.icon = ICON_COLOR;
+ break;
+ case SEQ_TYPE_TEXT:
+ data.icon = ICON_FONT_DATA;
+ break;
+ case SEQ_TYPE_ADD:
+ case SEQ_TYPE_SUB:
+ case SEQ_TYPE_MUL:
+ case SEQ_TYPE_OVERDROP:
+ case SEQ_TYPE_ALPHAOVER:
+ case SEQ_TYPE_ALPHAUNDER:
+ case SEQ_TYPE_COLORMIX:
+ case SEQ_TYPE_MULTICAM:
+ case SEQ_TYPE_TRANSFORM:
+ case SEQ_TYPE_SPEED:
+ case SEQ_TYPE_GLOW:
+ case SEQ_TYPE_GAUSSIAN_BLUR:
+ data.icon = ICON_SHADERFX;
+ break;
+ case SEQ_TYPE_CROSS:
+ case SEQ_TYPE_GAMCROSS:
+ case SEQ_TYPE_WIPE:
+ data.icon = ICON_ARROW_LEFTRIGHT;
+ break;
+ case SEQ_TYPE_META:
+ data.icon = ICON_SEQ_STRIP_META;
+ break;
+ default:
+ data.icon = ICON_DOT;
+ break;
}
break;
case TSE_SEQ_STRIP:
data.icon = ICON_LIBRARY_DATA_DIRECT;
break;
case TSE_SEQUENCE_DUP:
- data.icon = ICON_OBJECT_DATA;
+ data.icon = ICON_SEQ_STRIP_DUPLICATE;
break;
case TSE_RNA_STRUCT:
if (RNA_struct_is_ID(te->rnaptr.type)) {
@@ -2459,7 +2629,11 @@ static void tselem_draw_icon(uiBlock *block,
return;
}
+ /* Icon is covered by restrict buttons */
if (!is_clickable || x >= xmax) {
+ /* Reduce alpha to match icon buttons */
+ alpha *= 0.8f;
+
/* placement of icons, copied from interface_widgets.c */
float aspect = (0.8f * UI_UNIT_Y) / ICON_DEFAULT_HEIGHT;
x += 2.0f * aspect;
@@ -2567,7 +2741,6 @@ static void outliner_draw_iconrow_doit(uiBlock *block,
float ufac = UI_UNIT_X / 20.0f;
float icon_color[4], icon_border[4];
outliner_icon_background_colors(icon_color, icon_border);
- icon_color[3] *= alpha_fac;
if (active == OL_DRAWSEL_ACTIVE) {
UI_GetThemeColor4fv(TH_EDITED_OBJECT, icon_color);
icon_border[3] = 0.3f;
@@ -2592,6 +2765,9 @@ static void outliner_draw_iconrow_doit(uiBlock *block,
GPU_blend(true); /* Roundbox disables. */
}
+ if (tselem->flag & TSE_HIGHLIGHTED) {
+ alpha_fac += 0.5;
+ }
tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, alpha_fac, false);
te->xs = *offsx;
te->ys = ys;
@@ -2599,7 +2775,12 @@ static void outliner_draw_iconrow_doit(uiBlock *block,
if (num_elements > 1) {
outliner_draw_iconrow_number(fstyle, *offsx, ys, num_elements);
+ te->flag |= TE_ICONROW_MERGED;
}
+ else {
+ te->flag |= TE_ICONROW;
+ }
+
(*offsx) += UI_UNIT_X;
}
@@ -2609,7 +2790,7 @@ static void outliner_draw_iconrow_doit(uiBlock *block,
* We use a continuum of indices until we get to the object data-blocks
* and we then make room for the object types.
*/
-static int tree_element_id_type_to_index(TreeElement *te)
+int tree_element_id_type_to_index(TreeElement *te)
{
TreeStoreElem *tselem = TREESTORE(te);
@@ -2739,7 +2920,7 @@ static void outliner_set_coord_tree_element(TreeElement *te, int startx, int sta
TreeElement *ten;
/* closed items may be displayed in row of parent, don't change their coordinate! */
- if ((te->flag & TE_ICONROW) == 0) {
+ if ((te->flag & TE_ICONROW) == 0 && (te->flag & TE_ICONROW_MERGED) == 0) {
/* store coord and continue, we need coordinates for elements outside view too */
te->xs = startx;
te->ys = starty;
@@ -3193,6 +3374,7 @@ static void outliner_draw_highlights_recursive(unsigned pos,
const SpaceOutliner *soops,
const ListBase *lb,
const float col_selection[4],
+ const float col_active[4],
const float col_highlight[4],
const float col_searchmatch[4],
int start_x,
@@ -3206,7 +3388,11 @@ static void outliner_draw_highlights_recursive(unsigned pos,
const int start_y = *io_start_y;
/* selection status */
- if (tselem->flag & TSE_SELECTED) {
+ if ((tselem->flag & TSE_ACTIVE) && (tselem->flag & TSE_SELECTED)) {
+ immUniformColor4fv(col_active);
+ immRecti(pos, 0, start_y, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y);
+ }
+ else if (tselem->flag & TSE_SELECTED) {
immUniformColor4fv(col_selection);
immRecti(pos, 0, start_y, (int)ar->v2d.cur.xmax, start_y + UI_UNIT_Y);
}
@@ -3260,6 +3446,7 @@ static void outliner_draw_highlights_recursive(unsigned pos,
soops,
&te->subtree,
col_selection,
+ col_active,
col_highlight,
col_searchmatch,
start_x + UI_UNIT_X,
@@ -3271,10 +3458,12 @@ static void outliner_draw_highlights_recursive(unsigned pos,
static void outliner_draw_highlights(ARegion *ar, SpaceOutliner *soops, int startx, int *starty)
{
const float col_highlight[4] = {1.0f, 1.0f, 1.0f, 0.13f};
- float col_selection[4], col_searchmatch[4];
+ float col_selection[4], col_active[4], col_searchmatch[4];
UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col_selection);
col_selection[3] = 1.0f; /* no alpha */
+ UI_GetThemeColor3fv(TH_SELECT_ACTIVE, col_active);
+ col_active[3] = 1.0f; /* no alpha */
UI_GetThemeColor4fv(TH_MATCH, col_searchmatch);
col_searchmatch[3] = 0.5f;
@@ -3282,8 +3471,16 @@ static void outliner_draw_highlights(ARegion *ar, SpaceOutliner *soops, int star
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, startx, starty);
+ outliner_draw_highlights_recursive(pos,
+ ar,
+ soops,
+ &soops->tree,
+ col_selection,
+ col_active,
+ col_highlight,
+ col_searchmatch,
+ startx,
+ starty);
immUnbindProgram();
GPU_blend(false);
}
@@ -3439,6 +3636,17 @@ void draw_outliner(const bContext *C)
outliner_build_tree(mainvar, scene, view_layer, soops, ar); // always
+ /* If global sync select is dirty, flag other outliners */
+ if (ED_outliner_select_sync_is_dirty(C)) {
+ ED_outliner_select_sync_flag_outliners(C);
+ }
+
+ /* Sync selection state from view layer */
+ if (!ELEM(soops->outlinevis, SO_LIBRARIES, SO_DATA_API, SO_ID_ORPHANS) &&
+ soops->flag & SO_SYNC_SELECT) {
+ outliner_sync_selection(C, soops);
+ }
+
/* force display to pixel coords */
v2d->flag |= (V2D_PIXELOFS_X | V2D_PIXELOFS_Y);
/* set matrix for 2d-view controls */
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index de6e89e47c4..943993cb810 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -101,9 +101,15 @@ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const
ARegion *ar = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- const float my = UI_view2d_region_to_view_y(&ar->v2d, event->mval[1]);
- TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, my);
+ float view_mval[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+
+ TreeElement *hovered_te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+
+ if (hovered_te) {
+ hovered_te = outliner_find_item_at_x_in_row(soops, hovered_te, view_mval[0], NULL);
+ }
bool changed = false;
if (!hovered_te || !(hovered_te->store_elem->flag & TSE_HIGHLIGHTED)) {
@@ -134,59 +140,108 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot)
/* Toggle Open/Closed ------------------------------------------- */
-static int do_outliner_item_openclose(
- bContext *C, SpaceOutliner *soops, TreeElement *te, const bool all, const float mval[2])
+/* Open or close a tree element, optionally toggling all children recursively */
+void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all)
{
+ TreeStoreElem *tselem = TREESTORE(te);
- if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
- TreeStoreElem *tselem = TREESTORE(te);
+ if (open) {
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ else {
+ tselem->flag |= TSE_CLOSED;
+ }
- /* all below close/open? */
- if (all) {
- tselem->flag &= ~TSE_CLOSED;
- outliner_flag_set(
- &te->subtree, TSE_CLOSED, !outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1));
- }
- else {
- if (tselem->flag & TSE_CLOSED) {
- tselem->flag &= ~TSE_CLOSED;
- }
- else {
- tselem->flag |= TSE_CLOSED;
+ if (toggle_all) {
+ outliner_flag_set(&te->subtree, TSE_CLOSED, !open);
+ }
+}
+
+typedef struct OpenCloseData {
+ TreeStoreElem *prev_tselem;
+ bool open;
+ int x_location;
+} OpenCloseData;
+
+static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+
+ float view_mval[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+
+ if (event->type == MOUSEMOVE) {
+ TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+
+ OpenCloseData *data = (OpenCloseData *)op->customdata;
+
+ /* Only openclose if mouse is not over the previously toggled element */
+ if (te && TREESTORE(te) != data->prev_tselem) {
+
+ /* Only toggle openclose on the same level as the first clicked element */
+ if (te->xs == data->x_location) {
+ outliner_item_openclose(te, data->open, false);
+ ED_region_tag_redraw(ar);
}
}
- return 1;
+ if (te) {
+ data->prev_tselem = TREESTORE(te);
+ }
+ else {
+ data->prev_tselem = NULL;
+ }
}
+ else if (event->val == KM_RELEASE) {
+ MEM_freeN(op->customdata);
- for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_openclose(C, soops, te, all, mval)) {
- return 1;
- }
+ return OPERATOR_FINISHED;
}
- return 0;
+
+ return OPERATOR_RUNNING_MODAL;
}
-/* event can enterkey, then it opens/closes */
-static int outliner_item_openclose(bContext *C, wmOperator *op, const wmEvent *event)
+static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- TreeElement *te;
- float fmval[2];
- const bool all = RNA_boolean_get(op->ptr, "all");
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ const bool toggle_all = RNA_boolean_get(op->ptr, "all");
- for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_openclose(C, soops, te, all, fmval)) {
- break;
+ float view_mval[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+
+ TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+
+ if (te && outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ const bool open = (tselem->flag & TSE_CLOSED) ||
+ (toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1)));
+
+ outliner_item_openclose(te, open, toggle_all);
+ ED_region_tag_redraw(ar);
+
+ /* Only toggle once for single click toggling */
+ if (event->type == LEFTMOUSE) {
+ return OPERATOR_FINISHED;
}
- }
- ED_region_tag_redraw(ar);
+ /* Store last expanded tselem and x coordinate of disclosure triangle */
+ OpenCloseData *toggle_data = MEM_callocN(sizeof(OpenCloseData), "open_close_data");
+ toggle_data->prev_tselem = tselem;
+ toggle_data->open = open;
+ toggle_data->x_location = te->xs;
- return OPERATOR_FINISHED;
+ /* Store the first clicked on element */
+ op->customdata = toggle_data;
+
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
void OUTLINER_OT_item_openclose(wmOperatorType *ot)
@@ -195,11 +250,12 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
ot->idname = "OUTLINER_OT_item_openclose";
ot->description = "Toggle whether item under cursor is enabled or closed";
- ot->invoke = outliner_item_openclose;
+ ot->invoke = outliner_item_openclose_invoke;
+ ot->modal = outliner_item_openclose_modal;
ot->poll = ED_operator_outliner_active;
- RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items");
+ RNA_def_boolean(ot->srna, "all", false, "All", "Close or open all items");
}
/* -------------------------------------------------------------------- */
@@ -330,10 +386,10 @@ void item_rename_cb(bContext *C,
do_item_rename(ar, te, tselem, reports);
}
-static int do_outliner_item_rename(ReportList *reports,
- ARegion *ar,
- TreeElement *te,
- const float mval[2])
+static void do_outliner_item_rename(ReportList *reports,
+ ARegion *ar,
+ TreeElement *te,
+ const float mval[2])
{
if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
TreeStoreElem *tselem = TREESTORE(te);
@@ -341,17 +397,12 @@ static int do_outliner_item_rename(ReportList *reports,
/* click on name */
if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) {
do_item_rename(ar, te, tselem, reports);
- return 1;
}
- return 0;
}
for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_rename(reports, ar, te, mval)) {
- return 1;
- }
+ do_outliner_item_rename(reports, ar, te, mval);
}
- return 0;
}
static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *event)
@@ -360,25 +411,34 @@ static int outliner_item_rename(bContext *C, wmOperator *op, const wmEvent *even
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te;
float fmval[2];
- bool changed = false;
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ /* Rename active element if key pressed, otherwise rename element at cursor coordinates */
+ if (event->val == KM_PRESS) {
+ TreeElement *active_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE);
- for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_rename(op->reports, ar, te, fmval)) {
- changed = true;
- break;
+ if (active_element) {
+ do_item_rename(ar, active_element, TREESTORE(active_element), op->reports);
+ }
+ else {
+ BKE_report(op->reports, RPT_WARNING, "No active item to rename");
}
}
+ else {
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- return changed ? OPERATOR_FINISHED : OPERATOR_PASS_THROUGH;
+ for (te = soops->tree.first; te; te = te->next) {
+ do_outliner_item_rename(op->reports, ar, te, fmval);
+ }
+ }
+
+ return OPERATOR_FINISHED;
}
void OUTLINER_OT_item_rename(wmOperatorType *ot)
{
ot->name = "Rename";
ot->idname = "OUTLINER_OT_item_rename";
- ot->description = "Rename item under cursor";
+ ot->description = "Rename the active element";
ot->invoke = outliner_item_rename;
@@ -1103,6 +1163,10 @@ static int outliner_select_all_exec(bContext *C, wmOperator *op)
break;
}
+ if (soops->flag & SO_SYNC_SELECT) {
+ ED_outliner_select_sync_from_outliner(C, soops);
+ }
+
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
ED_region_tag_redraw_no_rebuild(ar);
@@ -1179,20 +1243,17 @@ static int outliner_open_back(TreeElement *te)
return retval;
}
-static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
+/* Return element representing the active base or bone in the outliner, or NULL if none exists */
+static TreeElement *outliner_show_active_get_element(bContext *C,
+ SpaceOutliner *so,
+ ViewLayer *view_layer)
{
- SpaceOutliner *so = CTX_wm_space_outliner(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- ARegion *ar = CTX_wm_region(C);
- View2D *v2d = &ar->v2d;
-
TreeElement *te;
- int xdelta, ytop;
Object *obact = OBACT(view_layer);
if (!obact) {
- return OPERATOR_CANCELLED;
+ return NULL;
}
te = outliner_find_id(so, &so->tree, &obact->id);
@@ -1215,25 +1276,50 @@ static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
}
}
- if (te) {
- /* open up tree to active object/bone */
+ return te;
+}
+
+static void outliner_show_active(SpaceOutliner *so, ARegion *ar, TreeElement *te, ID *id)
+{
+ /* open up tree to active object/bone */
+ if (TREESTORE(te)->id == id) {
if (outliner_open_back(te)) {
outliner_set_coordinates(ar, so);
}
+ return;
+ }
+
+ for (TreeElement *ten = te->subtree.first; ten; ten = ten->next) {
+ outliner_show_active(so, ar, ten, id);
+ }
+}
+
+static int outliner_show_active_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ SpaceOutliner *so = CTX_wm_space_outliner(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ ARegion *ar = CTX_wm_region(C);
+ View2D *v2d = &ar->v2d;
+
+ TreeElement *active_element = outliner_show_active_get_element(C, so, view_layer);
- /* make te->ys center of view */
- ytop = te->ys + BLI_rcti_size_y(&v2d->mask) / 2;
- if (ytop > 0) {
- ytop = 0;
+ if (active_element) {
+ ID *id = TREESTORE(active_element)->id;
+
+ /* Expand all elements in the outliner with matching ID */
+ for (TreeElement *te = so->tree.first; te; te = te->next) {
+ outliner_show_active(so, ar, te, id);
}
- v2d->cur.ymax = (float)ytop;
- v2d->cur.ymin = (float)(ytop - BLI_rcti_size_y(&v2d->mask));
+ /* Center view on first element found */
+ int size_y = BLI_rcti_size_y(&v2d->mask) + 1;
+ int ytop = (active_element->ys + (size_y / 2));
+ int delta_y = ytop - v2d->cur.ymax;
- /* make te->xs ==> te->xend center of view */
- xdelta = (int)(te->xs - v2d->cur.xmin);
- v2d->cur.xmin += xdelta;
- v2d->cur.xmax += xdelta;
+ outliner_scroll_view(ar, delta_y);
+ }
+ else {
+ return OPERATOR_CANCELLED;
}
ED_region_tag_redraw_no_rebuild(ar);
@@ -1259,18 +1345,15 @@ void OUTLINER_OT_show_active(wmOperatorType *ot)
static int outliner_scroll_page_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
- int dy = BLI_rcti_size_y(&ar->v2d.mask);
- int up = 0;
+ int size_y = BLI_rcti_size_y(&ar->v2d.mask) + 1;
- if (RNA_boolean_get(op->ptr, "up")) {
- up = 1;
- }
+ bool up = RNA_boolean_get(op->ptr, "up");
- if (up == 0) {
- dy = -dy;
+ if (!up) {
+ size_y = -size_y;
}
- ar->v2d.cur.ymin += dy;
- ar->v2d.cur.ymax += dy;
+
+ outliner_scroll_view(ar, size_y);
ED_region_tag_redraw_no_rebuild(ar);
@@ -1697,7 +1780,7 @@ static void tree_element_to_path(TreeElement *te,
/* no ID, so check if entry is RNA-struct,
* and if that RNA-struct is an ID datablock to extract info from. */
if (tse->type == TSE_RNA_STRUCT) {
- /* ptr->data not ptr->id.data seems to be the one we want,
+ /* ptr->data not ptr->owner_id seems to be the one we want,
* since ptr->data is sometimes the owner of this ID? */
if (RNA_struct_is_ID(ptr->type)) {
*id = (ID *)ptr->data;
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index fa28d119244..95e37dea249 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -40,7 +40,6 @@ struct TreeStoreElem;
struct ViewLayer;
struct bContext;
struct bPoseChannel;
-struct wmEvent;
struct wmKeyConfig;
struct wmOperatorType;
@@ -50,6 +49,14 @@ typedef enum TreeElementInsertType {
TE_INSERT_INTO,
} TreeElementInsertType;
+/* Use generic walk select after D4771 is committed */
+typedef enum WalkSelectDirection {
+ OUTLINER_SELECT_WALK_UP,
+ OUTLINER_SELECT_WALK_DOWN,
+ OUTLINER_SELECT_WALK_LEFT,
+ OUTLINER_SELECT_WALK_RIGHT,
+} WalkSelectDirection;
+
typedef enum TreeTraversalAction {
/* Continue traversal regularly, don't skip children. */
TRAVERSE_CONTINUE = 0,
@@ -131,6 +138,9 @@ enum {
TE_DISABLED = (1 << 4),
TE_DRAGGING = (1 << 5),
TE_CHILD_NOT_IN_COLLECTION = (1 << 6),
+ /* Child elements of the same type in the icon-row are drawn merged as one icon.
+ * This flag is set for an element that is part of these merged child icons. */
+ TE_ICONROW_MERGED = (1 << 7),
};
/* button events */
@@ -223,6 +233,8 @@ void outliner_collection_isolate_flag(struct Scene *scene,
const char *propname,
const bool value);
+int tree_element_id_type_to_index(TreeElement *te);
+
/* outliner_select.c -------------------------------------------- */
eOLDrawState tree_element_type_active(struct bContext *C,
struct Scene *scene,
@@ -253,6 +265,10 @@ void outliner_object_mode_toggle(struct bContext *C,
ViewLayer *view_layer,
Base *base);
+void outliner_element_activate(struct SpaceOutliner *soops, struct TreeStoreElem *tselem);
+
+bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x);
+
/* outliner_edit.c ---------------------------------------------- */
typedef void (*outliner_operation_cb)(struct bContext *C,
struct ReportList *,
@@ -337,6 +353,8 @@ void item_object_mode_exit_cb(struct bContext *C,
void outliner_set_coordinates(struct ARegion *ar, struct SpaceOutliner *soops);
+void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all);
+
/* outliner_dragdrop.c */
void outliner_dropboxes(void);
@@ -364,6 +382,7 @@ void OUTLINER_OT_show_active(struct wmOperatorType *ot);
void OUTLINER_OT_show_hierarchy(struct wmOperatorType *ot);
void OUTLINER_OT_select_box(struct wmOperatorType *ot);
+void OUTLINER_OT_select_walk(struct wmOperatorType *ot);
void OUTLINER_OT_select_all(struct wmOperatorType *ot);
void OUTLINER_OT_expanded_toggle(struct wmOperatorType *ot);
@@ -380,6 +399,10 @@ void OUTLINER_OT_orphans_purge(struct wmOperatorType *ot);
/* outliner_tools.c ---------------------------------------------- */
+void merged_element_search_menu_invoke(struct bContext *C,
+ TreeElement *parent_te,
+ TreeElement *activate_te);
+
void OUTLINER_OT_operation(struct wmOperatorType *ot);
void OUTLINER_OT_scene_operation(struct wmOperatorType *ot);
void OUTLINER_OT_object_operation(struct wmOperatorType *ot);
@@ -439,7 +462,8 @@ TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops,
float view_co_y);
TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *soops,
const TreeElement *parent_te,
- float view_co_x);
+ float view_co_x,
+ bool *multiple_objects);
TreeElement *outliner_find_tse(struct SpaceOutliner *soops, const TreeStoreElem *tse);
TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem);
TreeElement *outliner_find_parent_element(ListBase *lb,
@@ -456,5 +480,12 @@ bool outliner_tree_traverse(const SpaceOutliner *soops,
TreeTraversalFunc func,
void *customdata);
float outliner_restrict_columns_width(const struct SpaceOutliner *soops);
+TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag);
+bool outliner_is_element_visible(const TreeElement *te);
+void outliner_scroll_view(struct ARegion *ar, int delta_y);
+
+/* outliner_sync.c ---------------------------------------------- */
+
+void outliner_sync_selection(const struct bContext *C, struct SpaceOutliner *soops);
#endif /* __OUTLINER_INTERN_H__ */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index f155a2d5f89..4b57d4ad771 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -50,6 +50,7 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_highlight_update);
WM_operatortype_append(OUTLINER_OT_item_activate);
WM_operatortype_append(OUTLINER_OT_select_box);
+ WM_operatortype_append(OUTLINER_OT_select_walk);
WM_operatortype_append(OUTLINER_OT_item_openclose);
WM_operatortype_append(OUTLINER_OT_item_rename);
WM_operatortype_append(OUTLINER_OT_item_drag_drop);
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 7f45c4d22fa..44e67fa1508 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -51,14 +51,16 @@
#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
#include "ED_armature.h"
+#include "ED_gpencil.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_sequencer.h"
#include "ED_undo.h"
-#include "ED_gpencil.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -251,9 +253,7 @@ static eOLDrawState active_viewlayer(bContext *C,
}
/**
- * Select object tree:
- * CTRL+LMB: Select/Deselect object and all children.
- * CTRL+SHIFT+LMB: Add/Remove object and all children.
+ * Select object tree
*/
static void do_outliner_object_select_recursive(ViewLayer *view_layer,
Object *ob_parent,
@@ -450,9 +450,9 @@ static eOLDrawState tree_element_active_material(bContext *C,
return OL_DRAWSEL_NONE;
}
-static eOLDrawState tree_element_active_camera(bContext *UNUSED(C),
+static eOLDrawState tree_element_active_camera(bContext *C,
Scene *scene,
- ViewLayer *UNUSED(sl),
+ ViewLayer *UNUSED(view_layer),
SpaceOutliner *soops,
TreeElement *te,
const eOLSetState set)
@@ -460,10 +460,21 @@ static eOLDrawState tree_element_active_camera(bContext *UNUSED(C),
Object *ob = (Object *)outliner_search_back(soops, te, ID_OB);
if (set != OL_SETSEL_NONE) {
+ scene->camera = ob;
+
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = bmain->wm.first;
+
+ WM_windows_scene_data_sync(&wm->windows, scene);
+ DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
+ DEG_relations_tag_update(bmain);
+ WM_event_add_notifier(C, NC_SCENE | NA_EDITED, NULL);
+
return OL_DRAWSEL_NONE;
}
-
- return scene->camera == ob;
+ else {
+ return scene->camera == ob;
+ }
}
static eOLDrawState tree_element_active_world(bContext *C,
@@ -1083,6 +1094,13 @@ eOLDrawState tree_element_type_active(bContext *C,
/* ================================================ */
+/* Activate a tree store element and set the walk navigation start element */
+void outliner_element_activate(SpaceOutliner *soops, TreeStoreElem *tselem)
+{
+ outliner_flag_set(&soops->tree, TSE_ACTIVE | TSE_ACTIVE_WALK, false);
+ tselem->flag |= TSE_ACTIVE | TSE_ACTIVE_WALK;
+}
+
/**
* Action when clicking to activate an item (typically under the mouse cursor),
* but don't do any cursor intersection checks.
@@ -1114,7 +1132,8 @@ static void do_outliner_item_activate_tree_element(bContext *C,
else if (tselem->type == TSE_POSE_BASE) {
/* Support pose mode toggle, keeping the active object as is. */
}
- else {
+ else if (soops->flag & SO_SYNC_SELECT) {
+ /* Only activate when synced selection is enabled */
tree_element_set_active_object(C,
scene,
view_layer,
@@ -1125,6 +1144,9 @@ static void do_outliner_item_activate_tree_element(bContext *C,
recursive && tselem->type == 0);
}
+ /* Mark as active in the outliner */
+ outliner_element_activate(soops, tselem);
+
if (tselem->type == 0) { // the lib blocks
/* editmode? */
if (te->idcode == ID_SCE) {
@@ -1189,7 +1211,7 @@ static void do_outliner_item_activate_tree_element(bContext *C,
tree_element_active(C, scene, view_layer, soops, te, OL_SETSEL_NORMAL, false);
}
}
- else {
+ else if (soops->flag & SO_SYNC_SELECT) {
tree_element_type_active(C,
scene,
view_layer,
@@ -1211,7 +1233,8 @@ void outliner_item_select(SpaceOutliner *soops,
const bool toggle)
{
TreeStoreElem *tselem = TREESTORE(te);
- const short new_flag = toggle ? (tselem->flag ^ TSE_SELECTED) : (tselem->flag | TSE_SELECTED);
+ const short new_flag = (toggle && (tselem->flag & TSE_ACTIVE)) ? (tselem->flag ^ TSE_SELECTED) :
+ (tselem->flag | TSE_SELECTED);
if (extend == false) {
outliner_flag_set(&soops->tree, TSE_SELECTED, false);
@@ -1219,24 +1242,72 @@ void outliner_item_select(SpaceOutliner *soops,
tselem->flag = new_flag;
}
-static void outliner_item_toggle_closed(TreeElement *te, const bool toggle_children)
+static bool do_outliner_range_select_recursive(ListBase *lb,
+ TreeElement *active,
+ TreeElement *cursor,
+ bool selecting)
{
- TreeStoreElem *tselem = TREESTORE(te);
- if (toggle_children) {
- tselem->flag &= ~TSE_CLOSED;
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
- const bool all_opened = !outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1);
- outliner_flag_set(&te->subtree, TSE_CLOSED, all_opened);
- }
- else {
- tselem->flag ^= TSE_CLOSED;
+ if (selecting) {
+ tselem->flag |= TSE_SELECTED;
+ }
+
+ /* Set state for selection */
+ if (te == active || te == cursor) {
+ selecting = !selecting;
+ }
+
+ if (selecting) {
+ tselem->flag |= TSE_SELECTED;
+ }
+
+ /* Don't look inside closed elements */
+ if (!(tselem->flag & TSE_CLOSED)) {
+ selecting = do_outliner_range_select_recursive(&te->subtree, active, cursor, selecting);
+ }
}
+
+ return selecting;
}
-static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x)
+/* Select a range of items between cursor and active element */
+static void do_outliner_range_select(bContext *C,
+ SpaceOutliner *soops,
+ TreeElement *cursor,
+ const bool extend)
{
- return ((te->flag & TE_ICONROW) == 0) && (view_co_x > te->xs) &&
- (view_co_x < te->xs + UI_UNIT_X);
+ TreeElement *active = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE);
+
+ /* If no active element exists, activate the element under the cursor */
+ if (!active) {
+ outliner_item_select(soops, cursor, false, false);
+ outliner_item_do_activate_from_tree_element(C, cursor, TREESTORE(cursor), false, false);
+ return;
+ }
+
+ TreeStoreElem *tselem = TREESTORE(active);
+ const bool active_selected = (tselem->flag & TSE_SELECTED);
+
+ if (!extend) {
+ outliner_flag_set(&soops->tree, TSE_SELECTED, false);
+ }
+
+ /* Select active if under cursor */
+ if (active == cursor) {
+ TREESTORE(cursor)->flag |= TSE_SELECTED;
+ return;
+ }
+
+ /* If active is not selected, select the element under the cursor */
+ if (!active_selected || !outliner_is_element_visible(active)) {
+ outliner_item_select(soops, cursor, false, false);
+ outliner_item_do_activate_from_tree_element(C, cursor, TREESTORE(cursor), false, false);
+ return;
+ }
+
+ do_outliner_range_select_recursive(&soops->tree, active, cursor, false);
}
static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops,
@@ -1247,7 +1318,7 @@ static bool outliner_is_co_within_restrict_columns(const SpaceOutliner *soops,
}
/**
- * A version of #outliner_item_do_acticate_from_cursor that takes the tree element directly.
+ * A version of #outliner_item_do_activate_from_cursor that takes the tree element directly.
* and doesn't depend on the pointer position.
*
* This allows us to simulate clicking on an item without dealing with the mouse cursor.
@@ -1271,10 +1342,11 @@ void outliner_item_do_activate_from_tree_element(
static int outliner_item_do_activate_from_cursor(bContext *C,
const int mval[2],
const bool extend,
- const bool recursive,
+ const bool use_range,
const bool deselect_all)
{
ARegion *ar = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
TreeElement *te;
float view_mval[2];
@@ -1292,28 +1364,36 @@ static int outliner_item_do_activate_from_cursor(bContext *C,
changed = true;
}
}
- else if (outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
- outliner_item_toggle_closed(te, extend);
- changed = true;
- rebuild_tree = true;
+ /* Don't allow toggle on scene collection */
+ else if ((TREESTORE(te)->type != TSE_VIEW_COLLECTION_BASE) &&
+ outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
else {
- Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- /* the row may also contain children, if one is hovered we want this instead of current te */
- TreeElement *activate_te = outliner_find_item_at_x_in_row(soops, te, view_mval[0]);
- TreeStoreElem *activate_tselem = TREESTORE(activate_te);
- outliner_item_select(soops, activate_te, extend, extend);
+ /* The row may also contain children, if one is hovered we want this instead of current te */
+ bool merged_elements = false;
+ TreeElement *activate_te = outliner_find_item_at_x_in_row(
+ soops, te, view_mval[0], &merged_elements);
- /* Only change modes when clicking on the icon/text,
- * otherwise we can't easily select without changing modes. */
- if ((te->flag & TE_ICONROW) == 0) {
- if (view_mval[0] >= te->xs && view_mval[0] <= te->xend) {
- do_outliner_item_activate_tree_element(
- C, scene, view_layer, soops, activate_te, activate_tselem, extend, recursive);
- }
+ /* If the selected icon was an aggregate of multiple elements, run the search popup */
+ if (merged_elements) {
+ merged_element_search_menu_invoke(C, te, activate_te);
+ return OPERATOR_CANCELLED;
+ }
+
+ TreeStoreElem *activate_tselem = TREESTORE(activate_te);
+
+ if (use_range) {
+ do_outliner_range_select(C, soops, activate_te, extend);
+ }
+ else {
+ outliner_item_select(soops, activate_te, extend, extend);
+ do_outliner_item_activate_tree_element(
+ C, scene, view_layer, soops, activate_te, activate_tselem, extend, false);
}
+
changed = true;
}
@@ -1324,7 +1404,10 @@ static int outliner_item_do_activate_from_cursor(bContext *C,
else {
ED_region_tag_redraw_no_rebuild(ar);
}
- ED_undo_push(C, "Outliner selection change");
+
+ if (soops->flag & SO_SYNC_SELECT) {
+ ED_outliner_select_sync_from_outliner(C, soops);
+ }
}
return OPERATOR_FINISHED;
@@ -1334,9 +1417,9 @@ static int outliner_item_do_activate_from_cursor(bContext *C,
static int outliner_item_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
const bool extend = RNA_boolean_get(op->ptr, "extend");
- const bool recursive = RNA_boolean_get(op->ptr, "recursive");
+ const bool use_range = RNA_boolean_get(op->ptr, "extend_range");
const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all");
- return outliner_item_do_activate_from_cursor(C, event->mval, extend, recursive, deselect_all);
+ return outliner_item_do_activate_from_cursor(C, event->mval, extend, use_range, deselect_all);
}
void OUTLINER_OT_item_activate(wmOperatorType *ot)
@@ -1349,9 +1432,14 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot)
ot->poll = ED_operator_outliner_active;
+ ot->flag |= OPTYPE_REGISTER | OPTYPE_UNDO;
+
PropertyRNA *prop;
RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection for activation");
- RNA_def_boolean(ot->srna, "recursive", false, "Recursive", "Select Objects and their children");
+ prop = RNA_def_boolean(
+ ot->srna, "extend_range", false, "Extend Range", "Select a range from active element");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
prop = RNA_def_boolean(ot->srna,
"deselect_all",
false,
@@ -1409,9 +1497,44 @@ static int outliner_box_select_exec(bContext *C, wmOperator *op)
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
ED_region_tag_redraw(ar);
+ if (soops->flag & SO_SYNC_SELECT) {
+ ED_outliner_select_sync_from_outliner(C, soops);
+ }
+
return OPERATOR_FINISHED;
}
+/* Find if x coordinate is over an icon or name */
+static bool outliner_item_is_co_over_name_icons(TreeElement *te, float view_co_x)
+{
+ /* Special case: count area left of Scene Collection as empty space */
+ bool outside_left = (TREESTORE(te)->type == TSE_VIEW_COLLECTION_BASE) ?
+ (view_co_x > te->xs + UI_UNIT_X) :
+ (view_co_x > te->xs);
+
+ return outside_left && (view_co_x < te->xend);
+}
+
+static int outliner_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+ float view_mval[2];
+ const bool tweak = RNA_boolean_get(op->ptr, "tweak");
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+
+ /* Find element clicked on */
+ TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+
+ /* Pass through if click is over name or icons, or not tweak event */
+ if (te && tweak && outliner_item_is_co_over_name_icons(te, view_mval[0])) {
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
+ }
+
+ return WM_gesture_box_invoke(C, op, event);
+}
+
void OUTLINER_OT_select_box(wmOperatorType *ot)
{
/* identifiers */
@@ -1420,7 +1543,7 @@ void OUTLINER_OT_select_box(wmOperatorType *ot)
ot->description = "Use box selection to select tree elements";
/* api callbacks */
- ot->invoke = WM_gesture_box_invoke;
+ ot->invoke = outliner_box_select_invoke;
ot->exec = outliner_box_select_exec;
ot->modal = WM_gesture_box_modal;
ot->cancel = WM_gesture_box_cancel;
@@ -1431,8 +1554,242 @@ void OUTLINER_OT_select_box(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
+ PropertyRNA *prop;
+
+ prop = RNA_def_boolean(
+ ot->srna, "tweak", false, "Tweak", "Tweak gesture from empty space for box selection");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+
WM_operator_properties_gesture_box(ot);
WM_operator_properties_select_operation_simple(ot);
}
/* ****************************************************** */
+
+/* **************** Walk Select Tool ****************** */
+
+/* Given a tree element return the rightmost child that is visible in the outliner */
+static TreeElement *outliner_find_rightmost_visible_child(SpaceOutliner *soops, TreeElement *te)
+{
+ while (te->subtree.last) {
+ if (TSELEM_OPEN(TREESTORE(te), soops)) {
+ te = te->subtree.last;
+ }
+ else {
+ break;
+ }
+ }
+ return te;
+}
+
+/* Find previous visible element in the tree */
+static TreeElement *outliner_find_previous_element(SpaceOutliner *soops, TreeElement *walk_element)
+{
+ if (walk_element->prev) {
+ walk_element = outliner_find_rightmost_visible_child(soops, walk_element->prev);
+ }
+ else if (walk_element->parent) {
+ /* Use parent if at beginning of list */
+ walk_element = walk_element->parent;
+ }
+
+ return walk_element;
+}
+
+/* Recursively search up the tree until a successor to a given element is found */
+static TreeElement *outliner_element_find_successor_in_parents(TreeElement *te)
+{
+ TreeElement *successor = te;
+ while (successor->parent) {
+ if (successor->parent->next) {
+ te = successor->parent->next;
+ break;
+ }
+ else {
+ successor = successor->parent;
+ }
+ }
+
+ return te;
+}
+
+/* Find next visible element in the tree */
+static TreeElement *outliner_find_next_element(SpaceOutliner *soops, TreeElement *walk_element)
+{
+ TreeStoreElem *tselem = TREESTORE(walk_element);
+
+ if (TSELEM_OPEN(tselem, soops) && walk_element->subtree.first) {
+ walk_element = walk_element->subtree.first;
+ }
+ else if (walk_element->next) {
+ walk_element = walk_element->next;
+ }
+ else {
+ walk_element = outliner_element_find_successor_in_parents(walk_element);
+ }
+
+ return walk_element;
+}
+
+static TreeElement *do_outliner_select_walk(SpaceOutliner *soops,
+ TreeElement *walk_element,
+ const int direction,
+ const bool extend,
+ const bool toggle_all)
+{
+ TreeStoreElem *tselem = TREESTORE(walk_element);
+
+ if (!extend) {
+ outliner_flag_set(&soops->tree, TSE_SELECTED, false);
+ }
+ tselem->flag &= ~TSE_ACTIVE_WALK;
+
+ switch (direction) {
+ case OUTLINER_SELECT_WALK_UP:
+ walk_element = outliner_find_previous_element(soops, walk_element);
+ break;
+ case OUTLINER_SELECT_WALK_DOWN:
+ walk_element = outliner_find_next_element(soops, walk_element);
+ break;
+ case OUTLINER_SELECT_WALK_LEFT:
+ outliner_item_openclose(walk_element, false, toggle_all);
+ break;
+ case OUTLINER_SELECT_WALK_RIGHT:
+ outliner_item_openclose(walk_element, true, toggle_all);
+ break;
+ }
+
+ TreeStoreElem *tselem_new = TREESTORE(walk_element);
+
+ /* If new element is already selected, deselect the previous element */
+ if (extend) {
+ tselem->flag = (tselem_new->flag & TSE_SELECTED) ? (tselem->flag & ~TSE_SELECTED) :
+ (tselem->flag | TSE_SELECTED);
+ }
+
+ tselem_new->flag |= TSE_SELECTED | TSE_ACTIVE_WALK;
+
+ return walk_element;
+}
+
+/* Find walk select element, or set it if it does not exist.
+ * Changed is set to true if walk element is found, false if it was set */
+static TreeElement *find_walk_select_start_element(SpaceOutliner *soops, bool *changed)
+{
+ TreeElement *walk_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE_WALK);
+
+ *changed = false;
+
+ /* If no walk element exists, start from active */
+ if (!walk_element) {
+ TreeElement *active_element = outliner_find_element_with_flag(&soops->tree, TSE_ACTIVE);
+
+ /* If no active element exists, use the first element in the tree */
+ if (!active_element) {
+ walk_element = soops->tree.first;
+ }
+ else {
+ walk_element = active_element;
+ }
+
+ *changed = true;
+ }
+
+ /* If walk element is not visible, set that element's first visible parent as walk element */
+ if (!outliner_is_element_visible(walk_element)) {
+ TREESTORE(walk_element)->flag &= ~TSE_ACTIVE_WALK;
+
+ while (!outliner_is_element_visible(walk_element)) {
+ walk_element = walk_element->parent;
+ }
+ *changed = true;
+ }
+
+ return walk_element;
+}
+
+/* Scroll the outliner when the walk element reaches the top or bottom boundary */
+static void outliner_walk_scroll(ARegion *ar, TreeElement *te)
+{
+ /* Account for the header height */
+ int y_max = ar->v2d.cur.ymax - UI_UNIT_Y;
+ int y_min = ar->v2d.cur.ymin;
+
+ /* Scroll if walked position is beyond the border */
+ if (te->ys > y_max) {
+ outliner_scroll_view(ar, te->ys - y_max);
+ }
+ else if (te->ys < y_min) {
+ outliner_scroll_view(ar, -(y_min - te->ys));
+ }
+}
+
+static int outliner_walk_select_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ const short direction = RNA_enum_get(op->ptr, "direction");
+ const bool extend = RNA_boolean_get(op->ptr, "extend");
+ const bool toggle_all = RNA_boolean_get(op->ptr, "toggle_all");
+
+ bool changed;
+ TreeElement *walk_element = find_walk_select_start_element(soops, &changed);
+
+ /* If finding the starting walk select element did not move the element, proceed to walk */
+ if (!changed) {
+ walk_element = do_outliner_select_walk(soops, walk_element, direction, extend, toggle_all);
+ }
+ else {
+ TREESTORE(walk_element)->flag |= TSE_SELECTED | TSE_ACTIVE_WALK;
+ }
+
+ /* Scroll outliner to focus on walk element */
+ outliner_walk_scroll(ar, walk_element);
+
+ if (soops->flag & SO_SYNC_SELECT) {
+ ED_outliner_select_sync_from_outliner(C, soops);
+ }
+ ED_region_tag_redraw(ar);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_select_walk(wmOperatorType *ot)
+{
+ static const EnumPropertyItem direction_items[] = {
+ {OUTLINER_SELECT_WALK_UP, "UP", 0, "Up", ""},
+ {OUTLINER_SELECT_WALK_DOWN, "DOWN", 0, "Down", ""},
+ {OUTLINER_SELECT_WALK_LEFT, "LEFT", 0, "Left", ""},
+ {OUTLINER_SELECT_WALK_RIGHT, "RIGHT", 0, "Right", ""},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ /* identifiers */
+ ot->name = "Walk Select";
+ ot->idname = "OUTLINER_OT_select_walk";
+ ot->description = "Use walk navigation to select tree elements";
+
+ /* api callbacks */
+ ot->invoke = outliner_walk_select_invoke;
+ ot->poll = ED_operator_outliner_active;
+
+ ot->flag |= OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop;
+ prop = RNA_def_enum(ot->srna,
+ "direction",
+ direction_items,
+ 0,
+ "Walk Direction",
+ "Select element in this direction");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection on walk");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ prop = RNA_def_boolean(
+ ot->srna, "toggle_all", false, "Toggle All", "Toggle open/close hierarchy");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+}
+
+/* ****************************************************** */
diff --git a/source/blender/editors/space_outliner/outliner_sync.c b/source/blender/editors/space_outliner/outliner_sync.c
new file mode 100644
index 00000000000..29c820bce92
--- /dev/null
+++ b/source/blender/editors/space_outliner/outliner_sync.c
@@ -0,0 +1,575 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup spoutliner
+ */
+
+#include <stdio.h>
+
+#include "DNA_armature_types.h"
+#include "DNA_layer_types.h"
+#include "DNA_outliner_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_sequence_types.h"
+#include "DNA_space_types.h"
+
+#include "BLI_compiler_compat.h"
+#include "BLI_ghash.h"
+
+#include "BKE_armature.h"
+#include "BKE_context.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_sequencer.h"
+
+#include "DEG_depsgraph.h"
+
+#include "ED_armature.h"
+#include "ED_object.h"
+#include "ED_outliner.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "outliner_intern.h"
+
+/* Functions for tagging outliner selection syncing is dirty from operators */
+void ED_outliner_select_sync_from_object_tag(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_OBJECT;
+}
+
+void ED_outliner_select_sync_from_edit_bone_tag(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE;
+}
+
+void ED_outliner_select_sync_from_pose_bone_tag(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE;
+}
+
+void ED_outliner_select_sync_from_sequence_tag(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE;
+}
+
+void ED_outliner_select_sync_from_all_tag(bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wm->outliner_sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL;
+}
+
+bool ED_outliner_select_sync_is_dirty(const bContext *C)
+{
+ wmWindowManager *wm = CTX_wm_manager(C);
+ return wm->outliner_sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_ALL;
+}
+
+/* Copy sync select dirty flag from window manager to all outliners to be synced lazily on draw */
+void ED_outliner_select_sync_flag_outliners(const bContext *C)
+{
+ Main *bmain = CTX_data_main(C);
+ wmWindowManager *wm = CTX_wm_manager(C);
+
+ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ for (SpaceLink *sl = sa->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_OUTLINER) {
+ SpaceOutliner *soutliner = (SpaceOutliner *)sl;
+
+ soutliner->sync_select_dirty |= wm->outliner_sync_select_dirty;
+ }
+ }
+ }
+ }
+
+ /* Clear global sync flag */
+ wm->outliner_sync_select_dirty = 0;
+}
+
+/**
+ * Outliner sync select dirty flags are not enough to determine which types to sync,
+ * outliner display mode also needs to be considered. This stores the types of data
+ * to sync to increase code clarity.
+ */
+typedef struct SyncSelectTypes {
+ bool object;
+ bool edit_bone;
+ bool pose_bone;
+ bool sequence;
+} SyncSelectTypes;
+
+/**
+ * Set which types of data to sync when syncing selection from the outliner based on object
+ * interaction mode and outliner display mode
+ */
+static void outliner_sync_select_from_outliner_set_types(bContext *C,
+ SpaceOutliner *soops,
+ SyncSelectTypes *sync_types)
+{
+ Object *obact = CTX_data_active_object(C);
+ Object *obedit = CTX_data_edit_object(C);
+
+ const bool sequence_view = soops->outlinevis == SO_SEQUENCE;
+
+ sync_types->object = !sequence_view;
+ sync_types->edit_bone = !sequence_view && (obedit && obedit->type == OB_ARMATURE);
+ sync_types->pose_bone = !sequence_view && (obact && obact->mode == OB_MODE_POSE);
+ sync_types->sequence = sequence_view;
+}
+
+/**
+ * Current dirty flags and outliner display mode determine which type of syncing should occur.
+ * This is to ensure sync flag data is not lost on sync in the wrong display mode.
+ * Returns true if a sync is needed.
+ */
+static bool outliner_sync_select_to_outliner_set_types(const bContext *C,
+ SpaceOutliner *soops,
+ SyncSelectTypes *sync_types)
+{
+ Object *obact = CTX_data_active_object(C);
+ Object *obedit = CTX_data_edit_object(C);
+
+ const bool sequence_view = soops->outlinevis == SO_SEQUENCE;
+
+ sync_types->object = !sequence_view &&
+ (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_OBJECT);
+ sync_types->edit_bone = !sequence_view && (obedit && obedit->type == OB_ARMATURE) &&
+ (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE);
+ sync_types->pose_bone = !sequence_view && (obact && obact->mode == OB_MODE_POSE) &&
+ (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE);
+ sync_types->sequence = sequence_view &&
+ (soops->sync_select_dirty & WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE);
+
+ return sync_types->object || sync_types->edit_bone || sync_types->pose_bone ||
+ sync_types->sequence;
+}
+
+/**
+ * Stores items selected from a sync from the outliner. Prevents syncing the selection
+ * state of the last instance of an object linked in multiple collections.
+ */
+typedef struct SelectedItems {
+ GSet *objects;
+ GSet *edit_bones;
+ GSet *pose_bones;
+} SelectedItems;
+
+static void selected_items_init(SelectedItems *selected_items)
+{
+ selected_items->objects = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ selected_items->edit_bones = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+ selected_items->pose_bones = BLI_gset_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, __func__);
+}
+
+static void selected_items_free(SelectedItems *selected_items)
+{
+ BLI_gset_free(selected_items->objects, NULL);
+ BLI_gset_free(selected_items->edit_bones, NULL);
+ BLI_gset_free(selected_items->pose_bones, NULL);
+}
+
+/* Check if an instance of this object been selected by the sync */
+static bool is_object_selected(GSet *selected_objects, Base *base)
+{
+ return BLI_gset_haskey(selected_objects, base);
+}
+
+/* Check if an instance of this edit bone been selected by the sync */
+static bool is_edit_bone_selected(GSet *selected_ebones, EditBone *ebone)
+{
+ return BLI_gset_haskey(selected_ebones, ebone);
+}
+
+/* Check if an instance of this pose bone been selected by the sync */
+static bool is_pose_bone_selected(GSet *selected_pbones, bPoseChannel *pchan)
+{
+ return BLI_gset_haskey(selected_pbones, pchan);
+}
+
+/* Add element's data to selected item set */
+static void add_selected_item(GSet *selected, void *data)
+{
+ BLI_gset_add(selected, data);
+}
+
+static void outliner_select_sync_to_object(ViewLayer *view_layer,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ GSet *selected_objects)
+{
+ Object *ob = (Object *)tselem->id;
+ Base *base = (te->directdata) ? (Base *)te->directdata :
+ BKE_view_layer_base_find(view_layer, ob);
+
+ if (base && (base->flag & BASE_SELECTABLE)) {
+ if (tselem->flag & TSE_SELECTED) {
+ ED_object_base_select(base, BA_SELECT);
+
+ add_selected_item(selected_objects, base);
+ }
+ else if (!is_object_selected(selected_objects, base)) {
+ ED_object_base_select(base, BA_DESELECT);
+ }
+ }
+}
+
+static void outliner_select_sync_to_edit_bone(ViewLayer *view_layer,
+ TreeElement *te,
+ TreeStoreElem *tselem,
+ GSet *selected_ebones)
+{
+ bArmature *arm = (bArmature *)tselem->id;
+ EditBone *ebone = (EditBone *)te->directdata;
+
+ short bone_flag = ebone->flag;
+
+ if (EBONE_SELECTABLE(arm, ebone)) {
+ if (tselem->flag & TSE_SELECTED) {
+ ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+
+ add_selected_item(selected_ebones, ebone);
+ }
+ else if (!is_edit_bone_selected(selected_ebones, ebone)) {
+ ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
+ }
+ }
+
+ /* Tag if selection changed */
+ if (bone_flag != ebone->flag) {
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
+ DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, obedit);
+ }
+}
+
+static void outliner_select_sync_to_pose_bone(TreeElement *te,
+ TreeStoreElem *tselem,
+ GSet *selected_pbones)
+{
+ Object *ob = (Object *)tselem->id;
+ bArmature *arm = ob->data;
+ bPoseChannel *pchan = (bPoseChannel *)te->directdata;
+
+ short bone_flag = pchan->bone->flag;
+
+ if (PBONE_SELECTABLE(arm, pchan->bone)) {
+ if (tselem->flag & TSE_SELECTED) {
+ pchan->bone->flag |= BONE_SELECTED;
+
+ add_selected_item(selected_pbones, pchan);
+ }
+ else if (!is_pose_bone_selected(selected_pbones, pchan)) {
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ }
+
+ /* Tag if selection changed */
+ if (bone_flag != pchan->bone->flag) {
+ DEG_id_tag_update(&arm->id, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_OBJECT | ND_BONE_SELECT, ob);
+ }
+}
+
+static void outliner_select_sync_to_sequence(Scene *scene, TreeStoreElem *tselem)
+{
+ Sequence *seq = (Sequence *)tselem->id;
+
+ if (tselem->flag & TSE_ACTIVE) {
+ BKE_sequencer_active_set(scene, seq);
+ }
+
+ if (tselem->flag & TSE_SELECTED) {
+ seq->flag |= SELECT;
+ }
+ else {
+ seq->flag &= ~SELECT;
+ }
+}
+
+/** Sync select and active flags from outliner to active view layer, bones, and sequencer. */
+static void outliner_sync_selection_from_outliner(Scene *scene,
+ ViewLayer *view_layer,
+ ListBase *tree,
+ const SyncSelectTypes *sync_types,
+ SelectedItems *selected_items)
+{
+
+ for (TreeElement *te = tree->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (tselem->type == 0 && te->idcode == ID_OB) {
+ if (sync_types->object) {
+ outliner_select_sync_to_object(view_layer, te, tselem, selected_items->objects);
+ }
+ }
+ else if (tselem->type == TSE_EBONE) {
+ if (sync_types->edit_bone) {
+ outliner_select_sync_to_edit_bone(view_layer, te, tselem, selected_items->edit_bones);
+ }
+ }
+ else if (tselem->type == TSE_POSE_CHANNEL) {
+ if (sync_types->pose_bone) {
+ outliner_select_sync_to_pose_bone(te, tselem, selected_items->pose_bones);
+ }
+ }
+ else if (tselem->type == TSE_SEQUENCE) {
+ if (sync_types->sequence) {
+ outliner_select_sync_to_sequence(scene, tselem);
+ }
+ }
+
+ outliner_sync_selection_from_outliner(
+ scene, view_layer, &te->subtree, sync_types, selected_items);
+ }
+}
+
+/* Set clean outliner and mark other outliners for syncing */
+void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *soops)
+{
+ /* Don't sync in certain outliner display modes */
+ if (ELEM(soops->outlinevis, SO_LIBRARIES, SO_DATA_API, SO_ID_ORPHANS)) {
+ return;
+ }
+
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ SyncSelectTypes sync_types;
+ outliner_sync_select_from_outliner_set_types(C, soops, &sync_types);
+
+ /* To store elements that have been selected to prevent linked object sync errors */
+ SelectedItems selected_items;
+
+ selected_items_init(&selected_items);
+
+ outliner_sync_selection_from_outliner(
+ scene, view_layer, &soops->tree, &sync_types, &selected_items);
+
+ selected_items_free(&selected_items);
+
+ /* Tag for updates and clear dirty flag toprevent a sync to the outliner on draw */
+ if (sync_types.object) {
+ soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_OBJECT;
+ DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
+ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+ }
+ else if (sync_types.edit_bone) {
+ soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE;
+ }
+ else if (sync_types.pose_bone) {
+ soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE;
+ }
+ if (sync_types.sequence) {
+ soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE;
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
+ }
+}
+
+static void outliner_select_sync_from_object(ViewLayer *view_layer,
+ SpaceOutliner *soops,
+ Object *obact,
+ TreeElement *te,
+ TreeStoreElem *tselem)
+{
+ Object *ob = (Object *)tselem->id;
+ Base *base = (te->directdata) ? (Base *)te->directdata :
+ BKE_view_layer_base_find(view_layer, ob);
+ const bool is_selected = (base != NULL) && ((base->flag & BASE_SELECTED) != 0);
+
+ if (base && (ob == obact)) {
+ outliner_element_activate(soops, tselem);
+ }
+ else {
+ tselem->flag &= ~TSE_ACTIVE;
+ }
+
+ if (is_selected) {
+ tselem->flag |= TSE_SELECTED;
+ }
+ else {
+ tselem->flag &= ~TSE_SELECTED;
+ }
+}
+
+static void outliner_select_sync_from_edit_bone(SpaceOutliner *soops,
+ EditBone *ebone_active,
+ TreeElement *te,
+ TreeStoreElem *tselem)
+{
+ EditBone *ebone = (EditBone *)te->directdata;
+
+ if (ebone == ebone_active) {
+ outliner_element_activate(soops, tselem);
+ }
+ else {
+ tselem->flag &= ~TSE_ACTIVE;
+ }
+
+ if (ebone->flag & BONE_SELECTED) {
+ tselem->flag |= TSE_SELECTED;
+ }
+ else {
+ tselem->flag &= ~TSE_SELECTED;
+ }
+}
+
+static void outliner_select_sync_from_pose_bone(SpaceOutliner *soops,
+ bPoseChannel *pchan_active,
+ TreeElement *te,
+ TreeStoreElem *tselem)
+{
+ bPoseChannel *pchan = (bPoseChannel *)te->directdata;
+ Bone *bone = pchan->bone;
+
+ if (pchan == pchan_active) {
+ outliner_element_activate(soops, tselem);
+ }
+ else {
+ tselem->flag &= ~TSE_ACTIVE;
+ }
+
+ if (bone->flag & BONE_SELECTED) {
+ tselem->flag |= TSE_SELECTED;
+ }
+ else {
+ tselem->flag &= ~TSE_SELECTED;
+ }
+}
+
+static void outliner_select_sync_from_sequence(SpaceOutliner *soops,
+ Sequence *sequence_active,
+ TreeStoreElem *tselem)
+{
+ Sequence *seq = (Sequence *)tselem->id;
+
+ if (seq == sequence_active) {
+ outliner_element_activate(soops, tselem);
+ }
+ else {
+ tselem->flag &= ~TSE_ACTIVE;
+ }
+
+ if (seq->flag & SELECT) {
+ tselem->flag |= TSE_SELECTED;
+ }
+ else {
+ tselem->flag &= ~TSE_SELECTED;
+ }
+}
+
+/**
+ * Contains active object, bones, and sequence for syncing to prevent getting active data
+ * repeatedly throughout syncing to the outliner.
+ */
+typedef struct SyncSelectActiveData {
+ Object *object;
+ EditBone *edit_bone;
+ bPoseChannel *pose_channel;
+ Sequence *sequence;
+} SyncSelectActiveData;
+
+/** Sync select and active flags from active view layer, bones, and sequences to the outliner. */
+static void outliner_sync_selection_to_outliner(ViewLayer *view_layer,
+ SpaceOutliner *soops,
+ ListBase *tree,
+ SyncSelectActiveData *active_data,
+ const SyncSelectTypes *sync_types)
+{
+ for (TreeElement *te = tree->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (tselem->type == 0 && te->idcode == ID_OB) {
+ if (sync_types->object) {
+ outliner_select_sync_from_object(view_layer, soops, active_data->object, te, tselem);
+ }
+ }
+ else if (tselem->type == TSE_EBONE) {
+ if (sync_types->edit_bone) {
+ outliner_select_sync_from_edit_bone(soops, active_data->edit_bone, te, tselem);
+ }
+ }
+ else if (tselem->type == TSE_POSE_CHANNEL) {
+ if (sync_types->pose_bone) {
+ outliner_select_sync_from_pose_bone(soops, active_data->pose_channel, te, tselem);
+ }
+ }
+ else if (tselem->type == TSE_SEQUENCE) {
+ if (sync_types->sequence) {
+ outliner_select_sync_from_sequence(soops, active_data->sequence, tselem);
+ }
+ }
+ else {
+ tselem->flag &= ~TSE_SELECTED;
+ }
+
+ /* Sync subtree elements */
+ outliner_sync_selection_to_outliner(view_layer, soops, &te->subtree, active_data, sync_types);
+ }
+}
+
+/* Get active data from context */
+static void get_sync_select_active_data(const bContext *C, SyncSelectActiveData *active_data)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ active_data->object = OBACT(view_layer);
+ active_data->edit_bone = CTX_data_active_bone(C);
+ active_data->pose_channel = CTX_data_active_pose_bone(C);
+ active_data->sequence = BKE_sequencer_active_get(scene);
+}
+
+/* If outliner is dirty sync selection from view layer and sequwncer */
+void outliner_sync_selection(const bContext *C, SpaceOutliner *soops)
+{
+ /* Set which types of data to sync from sync dirty flag and outliner display mode */
+ SyncSelectTypes sync_types;
+ const bool sync_required = outliner_sync_select_to_outliner_set_types(C, soops, &sync_types);
+
+ if (sync_required) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+
+ /* Store active object, bones, and sequence */
+ SyncSelectActiveData active_data;
+ get_sync_select_active_data(C, &active_data);
+
+ outliner_sync_selection_to_outliner(
+ view_layer, soops, &soops->tree, &active_data, &sync_types);
+
+ /* Keep any unsynced data in the dirty flag */
+ if (sync_types.object) {
+ soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_OBJECT;
+ }
+ if (sync_types.edit_bone) {
+ soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE;
+ }
+ if (sync_types.pose_bone) {
+ soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE;
+ }
+ if (sync_types.sequence) {
+ soops->sync_select_dirty &= ~WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE;
+ }
+ }
+}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index f9905cc4fcd..a2d988f1142 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -63,6 +63,7 @@
#include "ED_armature.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_scene.h"
#include "ED_screen.h"
#include "ED_sequencer.h"
@@ -298,7 +299,7 @@ static void unlink_collection_cb(bContext *C,
}
else if (GS(tsep->id->name) == ID_SCE) {
Scene *scene = (Scene *)tsep->id;
- Collection *parent = BKE_collection_master(scene);
+ Collection *parent = scene->master_collection;
id_fake_user_set(&collection->id);
BKE_collection_child_remove(bmain, parent, collection);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
@@ -337,7 +338,7 @@ static void unlink_object_cb(bContext *C,
}
else if (GS(tsep->id->name) == ID_SCE) {
Scene *scene = (Scene *)tsep->id;
- Collection *parent = BKE_collection_master(scene);
+ Collection *parent = scene->master_collection;
BKE_collection_object_remove(bmain, parent, ob, true);
DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE);
DEG_relations_tag_update(bmain);
@@ -478,6 +479,129 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot)
}
/* ******************************************** */
+/**
+ * Stores the parent and a child element of a merged icon-row icon for
+ * the merged select popup menu. The sub-tree of the parent is searched and
+ * the child is needed to only show elements of the same type in the popup.
+ */
+typedef struct MergedSearchData {
+ TreeElement *parent_element;
+ TreeElement *select_element;
+} MergedSearchData;
+
+static void merged_element_search_cb_recursive(
+ const ListBase *tree, short tselem_type, short type, const char *str, uiSearchItems *items)
+{
+ char name[64];
+ int iconid;
+
+ for (TreeElement *te = tree->first; te; te = te->next) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (tree_element_id_type_to_index(te) == type && tselem_type == tselem->type) {
+ if (BLI_strcasestr(te->name, str)) {
+ BLI_strncpy(name, te->name, 64);
+
+ iconid = tree_element_get_icon(tselem, te).icon;
+
+ /* Don't allow duplicate named items */
+ if (UI_search_items_find_index(items, name) == -1) {
+ if (!UI_search_item_add(items, name, te, iconid)) {
+ break;
+ }
+ }
+ }
+ }
+
+ merged_element_search_cb_recursive(&te->subtree, tselem_type, type, str, items);
+ }
+}
+
+/* Get a list of elements that match the search string */
+static void merged_element_search_cb(const bContext *UNUSED(C),
+ void *data,
+ const char *str,
+ uiSearchItems *items)
+{
+ MergedSearchData *search_data = (MergedSearchData *)data;
+ TreeElement *parent = search_data->parent_element;
+ TreeElement *te = search_data->select_element;
+
+ int type = tree_element_id_type_to_index(te);
+
+ merged_element_search_cb_recursive(&parent->subtree, TREESTORE(te)->type, type, str, items);
+}
+
+/* Activate an element from the merged element search menu */
+static void merged_element_search_call_cb(struct bContext *C, void *UNUSED(arg1), void *element)
+{
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ TreeElement *te = (TreeElement *)element;
+
+ outliner_item_select(soops, te, false, false);
+ outliner_item_do_activate_from_tree_element(C, te, te->store_elem, false, false);
+
+ if (soops->flag & SO_SYNC_SELECT) {
+ ED_outliner_select_sync_from_outliner(C, soops);
+ }
+}
+
+/** Merged element search menu
+ * Created on activation of a merged or aggregated icon-row icon.
+ */
+static uiBlock *merged_element_search_menu(bContext *C, ARegion *ar, void *data)
+{
+ static char search[64] = "";
+ uiBlock *block;
+ uiBut *but;
+
+ /* Clear search on each menu creation */
+ *search = '\0';
+
+ block = UI_block_begin(C, ar, __func__, UI_EMBOSS);
+ UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU);
+ UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP);
+
+ short menu_width = 10 * UI_UNIT_X;
+ but = uiDefSearchBut(
+ block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, menu_width, UI_UNIT_Y, 0, 0, "");
+ UI_but_func_search_set(
+ but, NULL, merged_element_search_cb, data, false, merged_element_search_call_cb, NULL);
+ UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
+
+ /* Fake button to hold space for search items */
+ uiDefBut(block,
+ UI_BTYPE_LABEL,
+ 0,
+ "",
+ 10,
+ 10 - UI_searchbox_size_y(),
+ menu_width,
+ UI_searchbox_size_y(),
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ NULL);
+
+ /* Center the menu on the cursor */
+ UI_block_bounds_set_popup(block, 6, (const int[2]){-(menu_width / 2), 0});
+
+ return block;
+}
+
+void merged_element_search_menu_invoke(bContext *C,
+ TreeElement *parent_te,
+ TreeElement *activate_te)
+{
+ MergedSearchData *select_data = MEM_callocN(sizeof(MergedSearchData), "merge_search_data");
+ select_data->parent_element = parent_te;
+ select_data->select_element = activate_te;
+
+ UI_popup_block_invoke(C, merged_element_search_menu, select_data, MEM_freeN);
+}
+
static void object_select_cb(bContext *C,
ReportList *UNUSED(reports),
Scene *UNUSED(scene),
@@ -556,12 +680,7 @@ static void object_delete_cb(bContext *C,
if (ob == CTX_data_edit_object(C)) {
ED_object_editmode_exit(C, EM_FREEDATA);
}
- ED_object_base_free_and_unlink(CTX_data_main(C), scene, ob);
- /* leave for ED_outliner_id_unref to handle */
-#if 0
- te->directdata = NULL;
- tselem->id = NULL;
-#endif
+ BKE_id_delete(bmain, ob);
}
}
@@ -654,7 +773,7 @@ static void singleuser_action_cb(bContext *C,
if (id) {
IdAdtTemplate *iat = (IdAdtTemplate *)tsep->id;
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop;
RNA_pointer_create(&iat->id, &RNA_AnimData, iat->adt, &ptr);
@@ -677,7 +796,7 @@ static void singleuser_world_cb(bContext *C,
/* need to use parent scene not just scene, otherwise may end up getting wrong one */
if (id) {
Scene *parscene = (Scene *)tsep->id;
- PointerRNA ptr = {{NULL}};
+ PointerRNA ptr = {NULL};
PropertyRNA *prop;
RNA_id_pointer_create(&parscene->id, &ptr);
@@ -1080,11 +1199,6 @@ static void object_delete_hierarchy_cb(bContext *C,
}
outline_delete_hierarchy(C, reports, scene, base);
- /* leave for ED_outliner_id_unref to handle */
-#if 0
- te->directdata = NULL;
- tselem->id = NULL;
-#endif
}
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
@@ -1168,11 +1282,6 @@ static void object_batch_delete_hierarchy_cb(bContext *C,
}
outline_batch_delete_hierarchy(reports, CTX_data_main(C), view_layer, scene, base);
- /* leave for ED_outliner_id_unref to handle */
-#if 0
- te->directdata = NULL;
- tselem->id = NULL;
-#endif
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index cc062467dbe..fd6a052b84d 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -297,7 +297,7 @@ static void outliner_add_scene_contents(SpaceOutliner *soops,
ViewLayer *view_layer;
for (view_layer = sce->view_layers.first; view_layer; view_layer = view_layer->next) {
- TreeElement *tenlay = outliner_add_element(soops, &ten->subtree, sce, te, TSE_R_LAYER, 0);
+ TreeElement *tenlay = outliner_add_element(soops, &ten->subtree, sce, ten, TSE_R_LAYER, 0);
tenlay->name = view_layer->name;
tenlay->directdata = view_layer;
}
@@ -314,7 +314,7 @@ static void outliner_add_scene_contents(SpaceOutliner *soops,
ten = outliner_add_element(soops, lb, sce, te, TSE_SCENE_OBJECTS_BASE, 0);
ten->name = IFACE_("Objects");
FOREACH_SCENE_OBJECT_BEGIN (sce, ob) {
- outliner_add_element(soops, &ten->subtree, ob, NULL, 0, 0);
+ outliner_add_element(soops, &ten->subtree, ob, ten, 0, 0);
}
FOREACH_SCENE_OBJECT_END;
outliner_make_object_parent_hierarchy(&ten->subtree);
@@ -766,7 +766,7 @@ static TreeElement *outliner_add_element(
ID *id = idv;
if (ELEM(type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) {
- id = ((PointerRNA *)idv)->id.data;
+ id = ((PointerRNA *)idv)->owner_id;
if (!id) {
id = ((PointerRNA *)idv)->data;
}
@@ -1601,7 +1601,7 @@ typedef struct tTreeSort {
short idcode;
} tTreeSort;
-/* alphabetical comparator, tryping to put objects first */
+/* alphabetical comparator, trying to put objects first */
static int treesort_alpha_ob(const void *v1, const void *v2)
{
const tTreeSort *x1 = v1, *x2 = v2;
@@ -1627,7 +1627,7 @@ static int treesort_alpha_ob(const void *v1, const void *v2)
return (x1->te->flag & TE_CHILD_NOT_IN_COLLECTION) ? 1 : -1;
}
- comp = strcmp(x1->name, x2->name);
+ comp = BLI_strcasecmp_natural(x1->name, x2->name);
if (comp > 0) {
return 1;
@@ -1659,7 +1659,7 @@ static int treesort_alpha(const void *v1, const void *v2)
const tTreeSort *x1 = v1, *x2 = v2;
int comp;
- comp = strcmp(x1->name, x2->name);
+ comp = BLI_strcasecmp_natural(x1->name, x2->name);
if (comp > 0) {
return 1;
@@ -1697,7 +1697,7 @@ static int treesort_obtype_alpha(const void *v1, const void *v2)
}
}
else {
- int comp = strcmp(x1->name, x2->name);
+ int comp = BLI_strcasecmp_natural(x1->name, x2->name);
if (comp > 0) {
return 1;
@@ -2008,6 +2008,9 @@ static int outliner_exclude_filter_get(SpaceOutliner *soops)
case SO_FILTER_OB_VISIBLE:
exclude_filter |= SO_FILTER_OB_STATE_VISIBLE;
break;
+ case SO_FILTER_OB_HIDDEN:
+ exclude_filter |= SO_FILTER_OB_STATE_HIDDEN;
+ break;
case SO_FILTER_OB_SELECTED:
exclude_filter |= SO_FILTER_OB_STATE_SELECTED;
break;
@@ -2086,6 +2089,11 @@ static bool outliner_element_visible_get(ViewLayer *view_layer,
return false;
}
}
+ else if (exclude_filter & SO_FILTER_OB_STATE_HIDDEN) {
+ if ((base->flag & BASE_VISIBLE) != 0) {
+ return false;
+ }
+ }
else if (exclude_filter & SO_FILTER_OB_STATE_SELECTED) {
if ((base->flag & BASE_SELECTED) == 0) {
return false;
@@ -2339,7 +2347,8 @@ void outliner_build_tree(
te = outliner_add_element(soops, &soops->tree, sce, NULL, 0, 0);
tselem = TREESTORE(te);
- if (sce == scene && show_opened) {
+ /* New scene elements open by default */
+ if ((sce == scene && show_opened) || !tselem->used) {
tselem->flag &= ~TSE_CLOSED;
}
diff --git a/source/blender/editors/space_outliner/outliner_utils.c b/source/blender/editors/space_outliner/outliner_utils.c
index f57dce97b38..5dfdf6f129b 100644
--- a/source/blender/editors/space_outliner/outliner_utils.c
+++ b/source/blender/editors/space_outliner/outliner_utils.c
@@ -24,11 +24,15 @@
#include "BLI_utildefines.h"
#include "DNA_action_types.h"
+#include "DNA_screen_types.h"
#include "DNA_space_types.h"
+#include "BKE_context.h"
#include "BKE_outliner_treehash.h"
+#include "BKE_layer.h"
#include "ED_armature.h"
+#include "ED_outliner.h"
#include "UI_interface.h"
#include "UI_view2d.h"
@@ -62,6 +66,38 @@ TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops,
return NULL;
}
+static TreeElement *outliner_find_item_at_x_in_row_recursive(const TreeElement *parent_te,
+ float view_co_x,
+ bool *r_merged)
+{
+ TreeElement *child_te = parent_te->subtree.first;
+
+ bool over_element = false;
+
+ while (child_te) {
+ over_element = (view_co_x > child_te->xs) && (view_co_x < child_te->xend);
+ if ((child_te->flag & TE_ICONROW) && over_element) {
+ return child_te;
+ }
+ else if ((child_te->flag & TE_ICONROW_MERGED) && over_element) {
+ if (r_merged) {
+ *r_merged = true;
+ }
+ return child_te;
+ }
+
+ TreeElement *te = outliner_find_item_at_x_in_row_recursive(child_te, view_co_x, r_merged);
+ if (te != child_te) {
+ return te;
+ }
+
+ child_te = child_te->next;
+ }
+
+ /* return parent if no child is hovered */
+ return (TreeElement *)parent_te;
+}
+
/**
* Collapsed items can show their children as click-able icons. This function tries to find
* such an icon that represents the child item at x-coordinate \a view_co_x (view-space).
@@ -70,24 +106,14 @@ TreeElement *outliner_find_item_at_y(const SpaceOutliner *soops,
*/
TreeElement *outliner_find_item_at_x_in_row(const SpaceOutliner *soops,
const TreeElement *parent_te,
- float view_co_x)
+ float view_co_x,
+ bool *r_merged)
{
- /* if parent_te is opened, it doesn't show childs in row */
+ /* if parent_te is opened, it doesn't show children in row */
if (!TSELEM_OPEN(TREESTORE(parent_te), soops)) {
- /* no recursion, items can only display their direct children in the row */
- for (TreeElement *child_te = parent_te->subtree.first;
- /* don't look further if co_x is smaller than child position*/
- child_te && view_co_x >= child_te->xs;
-
- child_te = child_te->next) {
- if ((child_te->flag & TE_ICONROW) && (view_co_x > child_te->xs) &&
- (view_co_x < child_te->xend)) {
- return child_te;
- }
- }
+ return outliner_find_item_at_x_in_row_recursive(parent_te, view_co_x, r_merged);
}
- /* return parent if no child is hovered */
return (TreeElement *)parent_te;
}
@@ -300,3 +326,89 @@ float outliner_restrict_columns_width(const SpaceOutliner *soops)
}
return (num_columns * UI_UNIT_X + V2D_SCROLL_WIDTH);
}
+
+/* Find first tree element in tree with matching treestore flag */
+TreeElement *outliner_find_element_with_flag(const ListBase *lb, short flag)
+{
+ for (TreeElement *te = lb->first; te; te = te->next) {
+ if ((TREESTORE(te)->flag & flag) == flag) {
+ return te;
+ }
+ TreeElement *active_element = outliner_find_element_with_flag(&te->subtree, flag);
+ if (active_element) {
+ return active_element;
+ }
+ }
+ return NULL;
+}
+
+/* Find if element is visible in the outliner tree */
+bool outliner_is_element_visible(const TreeElement *te)
+{
+ TreeStoreElem *tselem;
+
+ while (te->parent) {
+ tselem = TREESTORE(te->parent);
+
+ if (tselem->flag & TSE_CLOSED) {
+ return false;
+ }
+ else {
+ te = te->parent;
+ }
+ }
+
+ return true;
+}
+
+/* Find if x coordinate is over element disclosure toggle */
+bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_co_x)
+{
+ return (view_co_x > te->xs) && (view_co_x < te->xs + UI_UNIT_X);
+}
+
+/* Scroll view vertically while keeping within total bounds */
+void outliner_scroll_view(ARegion *ar, int delta_y)
+{
+ int y_min = MIN2(ar->v2d.cur.ymin, ar->v2d.tot.ymin);
+
+ ar->v2d.cur.ymax += delta_y;
+ ar->v2d.cur.ymin += delta_y;
+
+ /* Adjust view if delta placed view outside total area */
+ int offset;
+ if (ar->v2d.cur.ymax > -UI_UNIT_Y) {
+ offset = ar->v2d.cur.ymax;
+ ar->v2d.cur.ymax -= offset;
+ ar->v2d.cur.ymin -= offset;
+ }
+ else if (ar->v2d.cur.ymin < y_min) {
+ offset = y_min - ar->v2d.cur.ymin;
+ ar->v2d.cur.ymax += offset;
+ ar->v2d.cur.ymin += offset;
+ }
+}
+
+/* Get base of object under cursor. Used for eyedropper tool */
+Base *ED_outliner_give_base_under_cursor(bContext *C, const int mval[2])
+{
+ ARegion *ar = CTX_wm_region(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+ TreeElement *te;
+ Base *base = NULL;
+ float view_mval[2];
+
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &view_mval[0], &view_mval[1]);
+
+ te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+ if (te) {
+ TreeStoreElem *tselem = TREESTORE(te);
+ if (tselem->type == 0) {
+ Object *ob = (Object *)tselem->id;
+ base = (te->directdata) ? (Base *)te->directdata : BKE_view_layer_base_find(view_layer, ob);
+ }
+ }
+
+ return base;
+}
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index 091efc56c09..79880c68120 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -131,6 +131,9 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win),
ED_region_tag_redraw(ar);
break;
}
+ if (wmn->action & NA_EDITED) {
+ ED_region_tag_redraw(ar);
+ }
break;
case NC_OBJECT:
switch (wmn->data) {
@@ -145,13 +148,8 @@ static void outliner_main_region_listener(wmWindow *UNUSED(win),
ED_region_tag_redraw(ar);
break;
case ND_CONSTRAINT:
- switch (wmn->action) {
- case NA_ADDED:
- case NA_REMOVED:
- case NA_RENAME:
- ED_region_tag_redraw(ar);
- break;
- }
+ /* all constraint actions now, for reordering */
+ ED_region_tag_redraw(ar);
break;
case ND_MODIFIER:
/* all modifier actions now */
@@ -304,6 +302,8 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
soutliner->filter_id_type = ID_GR;
soutliner->show_restrict_flags = SO_RESTRICT_ENABLE | SO_RESTRICT_HIDE;
soutliner->outlinevis = SO_VIEW_LAYER;
+ soutliner->sync_select_dirty |= WM_OUTLINER_SYNC_SELECT_FROM_ALL;
+ soutliner->flag |= SO_SYNC_SELECT;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for outliner");
@@ -349,6 +349,9 @@ static SpaceLink *outliner_duplicate(SpaceLink *sl)
soutlinern->treestore = NULL;
soutlinern->treehash = NULL;
+ soutlinern->flag |= (soutliner->flag & SO_SYNC_SELECT);
+ soutlinern->sync_select_dirty = WM_OUTLINER_SYNC_SELECT_FROM_ALL;
+
return (SpaceLink *)soutlinern;
}
@@ -415,7 +418,7 @@ void ED_spacetype_outliner(void)
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype outliner region");
art->regionid = RGN_TYPE_WINDOW;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
art->init = outliner_main_region_init;
art->draw = outliner_main_region_draw;
@@ -428,7 +431,7 @@ void ED_spacetype_outliner(void)
art = MEM_callocN(sizeof(ARegionType), "spacetype outliner header region");
art->regionid = RGN_TYPE_HEADER;
art->prefsizey = HEADERY;
- art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
+ art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
art->init = outliner_header_region_init;
art->draw = outliner_header_region_draw;
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 07350b5269e..b15acb12d00 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -1045,9 +1045,8 @@ ImBuf *sequencer_ibuf_get(struct Main *bmain,
bmain, depsgraph, scene, rectx, recty, proxy_size, false, &context);
context.view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
- /* sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
- * by Esc pressed somewhere in the past
- */
+ /* Sequencer could start rendering, in this case we need to be sure it wouldn't be canceled
+ * by Escape pressed somewhere in the past. */
G.is_break = false;
/* Rendering can change OGL context. Save & Restore framebuffer. */
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index ed0303564c6..22b73c32bfe 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -3405,6 +3405,7 @@ void SEQUENCER_OT_copy(wmOperatorType *ot)
/* identifiers */
ot->name = "Copy";
ot->idname = "SEQUENCER_OT_copy";
+ ot->description = "Copy selected strips to clipboard";
/* api callbacks */
ot->exec = sequencer_copy_exec;
@@ -3470,6 +3471,7 @@ void SEQUENCER_OT_paste(wmOperatorType *ot)
/* identifiers */
ot->name = "Paste";
ot->idname = "SEQUENCER_OT_paste";
+ ot->description = "Paste strips from clipboard";
/* api callbacks */
ot->exec = sequencer_paste_exec;
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index dd04260d80e..851d3b5f3aa 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -34,7 +34,6 @@ struct ARegionType;
struct Depsgraph;
struct Main;
struct Scene;
-struct ScrArea;
struct Sequence;
struct SpaceSeq;
struct StripElem;
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index 57f86059d9d..affb6d3fd88 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -41,6 +41,7 @@
/* for menu/popup icons etc etc*/
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_sequencer.h"
#include "ED_select_utils.h"
@@ -49,6 +50,7 @@
/* own include */
#include "sequencer_intern.h"
+
static void *find_nearest_marker(int UNUSED(d1), int UNUSED(d2))
{
return NULL;
@@ -254,6 +256,8 @@ static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
}
}
+ ED_outliner_select_sync_from_sequence_tag(C);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
@@ -293,6 +297,8 @@ static int sequencer_select_inverse_exec(bContext *C, wmOperator *UNUSED(op))
}
}
+ ED_outliner_select_sync_from_sequence_tag(C);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
@@ -542,6 +548,8 @@ static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *e
}
}
+ ED_outliner_select_sync_from_sequence_tag(C);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
/* allowing tweaks */
@@ -668,6 +676,8 @@ static int sequencer_select_more_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
+ ED_outliner_select_sync_from_sequence_tag(C);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
@@ -699,6 +709,8 @@ static int sequencer_select_less_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
}
+ ED_outliner_select_sync_from_sequence_tag(C);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
@@ -750,6 +762,8 @@ static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, cons
selected = select_more_less_seq__internal(scene, 1, 1);
}
+ ED_outliner_select_sync_from_sequence_tag(C);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
@@ -784,6 +798,8 @@ static int sequencer_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
selected = select_more_less_seq__internal(scene, true, true);
}
+ ED_outliner_select_sync_from_sequence_tag(C);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
@@ -832,6 +848,8 @@ static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
}
}
+ ED_outliner_select_sync_from_sequence_tag(C);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
@@ -876,6 +894,8 @@ static int sequencer_select_active_side_exec(bContext *C, wmOperator *op)
select_active_side(
ed->seqbasep, RNA_enum_get(op->ptr, "side"), seq_act->machine, seq_act->startdisp);
+ ED_outliner_select_sync_from_sequence_tag(C);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
@@ -934,6 +954,8 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op)
}
}
+ ED_outliner_select_sync_from_sequence_tag(C);
+
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
@@ -1311,6 +1333,7 @@ static int sequencer_select_grouped_exec(bContext *C, wmOperator *op)
}
if (changed) {
+ ED_outliner_select_sync_from_sequence_tag(C);
WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER | NA_SELECTED, scene);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c
index 9aa9d14cbc8..e1cf6d00b90 100644
--- a/source/blender/editors/space_sequencer/space_sequencer.c
+++ b/source/blender/editors/space_sequencer/space_sequencer.c
@@ -597,7 +597,7 @@ static void sequencer_main_region_message_subscribe(const struct bContext *UNUSE
&RNA_SequenceModifier,
&RNA_SequenceColorBalanceData,
};
- wmMsgParams_RNA msg_key_params = {{{0}}};
+ wmMsgParams_RNA msg_key_params = {{0}};
for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
msg_key_params.ptr.type = type_array[i];
WM_msg_subscribe_rna_params(
diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c
index c1a3c79b0d8..9f39313b9ab 100644
--- a/source/blender/editors/space_text/space_text.c
+++ b/source/blender/editors/space_text/space_text.c
@@ -29,6 +29,7 @@
#include "BLI_blenlib.h"
+#include "BKE_global.h"
#include "BKE_context.h"
#include "BKE_library.h"
#include "BKE_screen.h"
@@ -356,7 +357,7 @@ static void text_drop_paste(wmDrag *drag, wmDropBox *drop)
ID *id = WM_drag_ID(drag, 0);
/* copy drag path to properties */
- text = RNA_path_full_ID_py(id);
+ text = RNA_path_full_ID_py(G_MAIN, id);
RNA_string_set(drop->ptr, "text", text);
MEM_freeN(text);
}
diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index e1550deb659..caefb5070fb 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -142,7 +142,7 @@ static char *buf_tabs_to_spaces(const char *in_buf, const int tab_size)
BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x)
{
- /* add half the char width so mouse cursor selection is inbetween letters */
+ /* Add half the char width so mouse cursor selection is in between letters. */
return (x + (st->cwidth / 2)) / st->cwidth;
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 38e8d285c77..b412a72cce1 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -145,7 +145,7 @@ void ED_draw_object_facemap(Depsgraph *depsgraph,
facemap_data = CustomData_get_layer(&me->pdata, CD_FACEMAP);
- /* use gawain immediate mode fore now */
+ /* Make a batch and free it each time for now. */
const int looptris_len = poly_to_tri_count(mpoly_len, mloop_len);
const int vbo_len_capacity = looptris_len * 3;
int vbo_len_used = 0;
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 7acff998e2b..8c4f2f62602 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -992,7 +992,7 @@ static void view3d_main_region_message_subscribe(const struct bContext *C,
* accepting some redundant redraws.
*
* For other space types we might try avoid this, keep the 3D view as an exceptional case! */
- wmMsgParams_RNA msg_key_params = {{{0}}};
+ wmMsgParams_RNA msg_key_params = {{0}};
/* Only subscribe to types. */
StructRNA *type_array[] = {
@@ -1177,7 +1177,7 @@ static void view3d_header_region_message_subscribe(const struct bContext *UNUSED
struct ARegion *ar,
struct wmMsgBus *mbus)
{
- wmMsgParams_RNA msg_key_params = {{{0}}};
+ wmMsgParams_RNA msg_key_params = {{0}};
/* Only subscribe to types. */
StructRNA *type_array[] = {
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index 0045094542f..260546738f4 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -87,8 +87,7 @@ typedef struct View3DCameraControl {
float ofs_backup[3];
/* backup the views offset in case the user cancels flying in non camera mode */
- /* backup the views quat in case the user cancels flying in non camera mode.
- * (quat for view, eul for camera) */
+ /* backup the views quat in case the user cancels flying in non camera mode. */
float rot_backup[4];
/* remember if were ortho or not, only used for restoring the view if it was a ortho view */
char persp_backup;
@@ -209,8 +208,8 @@ void ED_view3d_cameracontrol_update(View3DCameraControl *vctrl,
const bool do_rotate,
const bool do_translate)
{
- /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera
- * to the view */
+ /* We are in camera view so apply the view offset and rotation to the view matrix
+ * and set the camera to the view. */
Scene *scene = vctrl->ctx_scene;
View3D *v3d = vctrl->ctx_v3d;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 6c534ee1b98..f6afa112f08 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -859,6 +859,51 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
return v3d->grid * ED_scene_grid_scale(scene, grid_unit);
}
+#define STEPS_LEN 8
+void ED_view3d_grid_steps(Scene *scene,
+ View3D *v3d,
+ RegionView3D *rv3d,
+ float r_grid_steps[STEPS_LEN])
+{
+ const void *usys;
+ int i, len;
+ bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
+ float grid_scale = v3d->grid;
+
+ if (usys) {
+ if (rv3d->view == RV3D_VIEW_USER) {
+ /* Skip steps */
+ len = bUnit_GetBaseUnit(usys) + 1;
+ }
+
+ grid_scale /= scene->unit.scale_length;
+
+ for (i = 0; i < len; i++) {
+ r_grid_steps[i] = (float)bUnit_GetScaler(usys, len - 1 - i) * grid_scale;
+ }
+ for (; i < STEPS_LEN; i++) {
+ /* Fill last slots */
+ r_grid_steps[i] = 10.0f * r_grid_steps[i - 1];
+ }
+ }
+ else {
+ if (rv3d->view != RV3D_VIEW_USER) {
+ /* Allow 3 more subdivisions. */
+ grid_scale /= powf(v3d->gridsubdiv, 3);
+ }
+ int subdiv = 1;
+ for (i = 0;; i++) {
+ r_grid_steps[i] = grid_scale * subdiv;
+
+ if (i == STEPS_LEN - 1) {
+ break;
+ }
+ subdiv *= v3d->gridsubdiv;
+ }
+ }
+}
+#undef STEPS_LEN
+
/* Simulates the grid scale that is actually viewed.
* The actual code is seen in `object_grid_frag.glsl` (see `grid_res`).
* Currently the simulation is only done when RV3D_VIEW_IS_AXIS. */
@@ -867,24 +912,35 @@ float ED_view3d_grid_view_scale(Scene *scene,
RegionView3D *rv3d,
const char **grid_unit)
{
- float grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
+ float grid_scale;
if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
/* Decrease the distance between grid snap points depending on zoom. */
- float grid_subdiv = v3d->gridsubdiv;
- if (grid_subdiv > 1) {
- /* Allow 3 more subdivisions (see OBJECT_engine_init). */
- grid_scale /= powf(grid_subdiv, 3);
-
- /* `3.0` was a value obtained by trial and error in order to get
- * a nice snap distance.*/
- float grid_res = 3.0 * (rv3d->dist / v3d->lens);
- float lvl = (logf(grid_res / grid_scale) / logf(grid_subdiv));
+ /* `0.38` was a value visually obtained in order to get a snap distance
+ * that matches previous versions Blender.*/
+ float min_dist = 0.38f * (rv3d->dist / v3d->lens);
+ float grid_steps[8];
+ ED_view3d_grid_steps(scene, v3d, rv3d, grid_steps);
+ int i;
+ for (i = 0; i < ARRAY_SIZE(grid_steps); i++) {
+ grid_scale = grid_steps[i];
+ if (grid_scale > min_dist) {
+ break;
+ }
+ }
- CLAMP_MIN(lvl, 0.0f);
+ if (grid_unit) {
+ const void *usys;
+ int len;
+ bUnit_GetSystem(scene->unit.system, B_UNIT_LENGTH, &usys, &len);
- grid_scale *= pow(grid_subdiv, (int)lvl);
+ if (usys) {
+ *grid_unit = bUnit_GetNameDisplay(usys, len - i - 1);
+ }
}
}
+ else {
+ grid_scale = ED_view3d_grid_scale(scene, v3d, grid_unit);
+ }
return grid_scale;
}
@@ -1360,6 +1416,27 @@ static void draw_selected_name(
BLF_disable(font_id, BLF_SHADOW);
}
+static void draw_grid_unit_name(
+ Scene *scene, RegionView3D *rv3d, View3D *v3d, int xoffset, int *yoffset)
+{
+ if (!rv3d->is_persp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ const char *grid_unit = NULL;
+ ED_view3d_grid_view_scale(scene, v3d, rv3d, &grid_unit);
+
+ if (grid_unit) {
+ char numstr[32] = "";
+ UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
+ if (v3d->grid != 1.0f) {
+ BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
+ }
+
+ *yoffset -= U.widget_unit;
+ BLF_draw_default_ascii(
+ xoffset, *yoffset, 0.0f, numstr[0] ? numstr : grid_unit, sizeof(numstr));
+ }
+ }
+}
+
/**
* Information drawn on top of the solid plates and composed data
*/
@@ -1421,19 +1498,10 @@ void view3d_draw_region_info(const bContext *C, ARegion *ar)
draw_selected_name(scene, view_layer, ob, xoffset, &yoffset);
}
-#if 0 /* TODO */
- if (grid_unit) { /* draw below the viewport name */
- char numstr[32] = "";
-
- UI_FontThemeColor(BLF_default(), TH_TEXT_HI);
- if (v3d->grid != 1.0f) {
- BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid);
- }
-
- *yoffset -= U.widget_unit;
- BLF_draw_default_ascii(xoffset, *yoffset, numstr[0] ? numstr : grid_unit, sizeof(numstr));
+ if (v3d->gridflag & (V3D_SHOW_FLOOR | V3D_SHOW_X | V3D_SHOW_Y | V3D_SHOW_Z)) {
+ /* draw below the viewport name */
+ draw_grid_unit_name(scene, rv3d, v3d, xoffset, &yoffset);
}
-#endif
}
if ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) {
@@ -1492,7 +1560,7 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
GPU_pass_cache_garbage_collect();
/* XXX This is in order to draw UI batches with the DRW
- * olg context since we now use it for drawing the entire area */
+ * old context since we now use it for drawing the entire area. */
gpu_batch_presets_reset();
/* No depth test for drawing action zones afterwards. */
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index 02ad481e6ce..d5772e5052a 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -162,6 +162,7 @@ static void validate_object_select_id(
Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
+ UNUSED_VARS_NDEBUG(ar);
if (obact_eval && (obact_eval->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT) ||
BKE_paint_select_face_test(obact_eval))) {
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 9a9fe81a13e..e76ef2b0458 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -404,9 +404,7 @@ static void viewops_data_create(bContext *C,
if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
if (ED_view3d_persp_ensure(depsgraph, vod->v3d, vod->ar)) {
/* If we're switching from camera view to the perspective one,
- * need to tag viewport update, so camera vuew and borders
- * are properly updated.
- */
+ * need to tag viewport update, so camera view and borders are properly updated. */
ED_region_tag_redraw(vod->ar);
}
}
@@ -4946,6 +4944,7 @@ void ED_view3d_cursor3d_position_rotation(bContext *C,
.use_object_edit_cage = false,
},
mval_fl,
+ NULL,
&dist_px,
ray_co,
ray_no,
@@ -5052,7 +5051,7 @@ void ED_view3d_cursor3d_update(bContext *C,
{
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- wmMsgParams_RNA msg_key_params = {{{0}}};
+ wmMsgParams_RNA msg_key_params = {{0}};
RNA_pointer_create(&scene->id, &RNA_View3DCursor, &scene->cursor, &msg_key_params.ptr);
WM_msg_publish_rna_params(mbus, &msg_key_params);
}
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index 1bb10697936..42931d5abb5 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -100,7 +100,7 @@ static void WIDGETGROUP_camera_setup(const bContext *C, wmGizmoGroup *gzgroup)
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);
+ WM_gizmo_set_flag(gz, WM_GIZMO_DRAW_HOVER | WM_GIZMO_DRAW_NO_SCALE, true);
UI_GetThemeColor3fv(TH_GIZMO_A, gz->color);
UI_GetThemeColor3fv(TH_GIZMO_HI, gz->color_hi);
@@ -152,9 +152,11 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup)
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 */
+ /* Need to set property here for undo. TODO would prefer to do this in _init */
+ PointerRNA camera_dof_ptr;
+ RNA_pointer_create(&ca->id, &RNA_CameraDOFSettings, &ca->dof, &camera_dof_ptr);
WM_gizmo_target_property_def_rna(
- cagzgroup->dop_dist, "offset", &camera_ptr, "dof.focus_distance", -1);
+ cagzgroup->dop_dist, "offset", &camera_dof_ptr, "focus_distance", -1);
}
else {
WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true);
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
index a984e339305..68159e2d684 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
@@ -77,7 +77,20 @@ static void gizmo_preselect_elem_draw(const bContext *UNUSED(C), wmGizmo *gz)
static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int mval[2])
{
+ wmEvent *event = CTX_wm_window(C)->eventstate;
MeshElemGizmo3D *gz_ele = (MeshElemGizmo3D *)gz;
+
+ /* Hack: Switch action mode based on key input */
+ const bool is_ctrl_pressed = WM_event_modifier_flag(event) & KM_CTRL;
+ const bool is_shift_pressed = WM_event_modifier_flag(event) & KM_SHIFT;
+ EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_TRANSFORM);
+ if (is_ctrl_pressed && !is_shift_pressed) {
+ EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_CREATE);
+ }
+ if (!is_ctrl_pressed && is_shift_pressed) {
+ EDBM_preselect_action_set(gz_ele->psel, PRESELECT_ACTION_DELETE);
+ }
+
struct {
Object *ob;
BMElem *ele;
@@ -87,18 +100,6 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
.dist = ED_view3d_select_dist_px(),
};
- struct {
- int base_index;
- int vert_index;
- int edge_index;
- int face_index;
- } prev = {
- .base_index = gz_ele->base_index,
- .vert_index = gz_ele->vert_index,
- .edge_index = gz_ele->edge_index,
- .face_index = gz_ele->face_index,
- };
-
{
ViewLayer *view_layer = CTX_data_view_layer(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -115,32 +116,66 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
{
/* TODO: support faces. */
- int base_index = -1;
+ int base_index_vert = -1;
+ int base_index_edge = -1;
+ int base_index_face = -1;
BMVert *eve_test;
BMEdge *eed_test;
+ BMFace *efa_test;
if (EDBM_unified_findnearest_from_raycast(&vc,
gz_ele->bases,
gz_ele->bases_len,
+ false,
true,
- &base_index,
+ &base_index_vert,
+ &base_index_edge,
+ &base_index_face,
&eve_test,
&eed_test,
- NULL)) {
- Base *base = gz_ele->bases[base_index];
- best.ob = base->object;
- if (eve_test) {
- best.ele = (BMElem *)eve_test;
- }
- else if (eed_test) {
- best.ele = (BMElem *)eed_test;
+ &efa_test)) {
+ if (EDBM_preselect_action_get(gz_ele->psel) == PRESELECT_ACTION_DELETE) {
+ /* Delete action */
+ if (efa_test) {
+ best.ele = (BMElem *)efa_test;
+ best.base_index = base_index_face;
+ }
}
+
else {
- BLI_assert(0);
+ /* Transform and create action */
+ if (eed_test) {
+ best.ele = (BMElem *)eed_test;
+ best.base_index = base_index_edge;
+ }
+ }
+
+ /* All actions use same vertex pre-selection. */
+ /* Re-topology should always prioritize edge pre-selection.
+ * Only pre-select a vertex when the cursor is really close to it. */
+ if (eve_test) {
+ BMVert *vert = (BMVert *)eve_test;
+ float vert_p_co[3], vert_co[3];
+ float mval_f[2] = {UNPACK2(vc.mval)};
+ mul_v3_m4v3(vert_co, gz_ele->bases[base_index_vert]->object->obmat, vert->co);
+ ED_view3d_project(vc.ar, vert_co, vert_p_co);
+ float len = len_v2v2(vert_p_co, mval_f);
+ if (len < 35) {
+ best.ele = (BMElem *)eve_test;
+ best.base_index = base_index_vert;
+ }
+ if (!BM_vert_is_boundary(vert) &&
+ EDBM_preselect_action_get(gz_ele->psel) != PRESELECT_ACTION_DELETE) {
+ best.ele = (BMElem *)eve_test;
+ best.base_index = base_index_vert;
+ }
}
- best.base_index = base_index;
+
/* Check above should never fail, if it does it's an internal error. */
BLI_assert(best.base_index != -1);
+
+ Base *base = gz_ele->bases[best.base_index];
+ best.ob = base->object;
}
}
@@ -167,32 +202,30 @@ static int gizmo_preselect_elem_test_select(bContext *C, wmGizmo *gz, const int
}
}
- if ((prev.base_index == gz_ele->base_index) && (prev.vert_index == gz_ele->vert_index) &&
- (prev.edge_index == gz_ele->edge_index) && (prev.face_index == gz_ele->face_index)) {
- /* pass (only recalculate on change) */
- }
- else {
- if (best.ele) {
- const float(*coords)[3] = NULL;
- {
- Object *ob = gz_ele->bases[gz_ele->base_index]->object;
- Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
- Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data);
- if (me_eval->runtime.edit_data) {
- coords = me_eval->runtime.edit_data->vertexCos;
- }
+ if (best.ele) {
+ const float(*coords)[3] = NULL;
+ {
+ Object *ob = gz_ele->bases[gz_ele->base_index]->object;
+ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ Mesh *me_eval = (Mesh *)DEG_get_evaluated_id(depsgraph, ob->data);
+ if (me_eval->runtime.edit_data) {
+ coords = me_eval->runtime.edit_data->vertexCos;
}
- EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords);
- }
- else {
- EDBM_preselect_elem_clear(gz_ele->psel);
}
+ EDBM_preselect_elem_update_from_single(gz_ele->psel, bm, best.ele, coords);
+ EDBM_preselect_elem_update_preview(gz_ele->psel, &vc, bm, best.ele, mval);
+ }
+ else {
+ EDBM_preselect_elem_clear(gz_ele->psel);
+ EDBM_preselect_preview_clear(gz_ele->psel);
+ }
- RNA_int_set(gz->ptr, "object_index", gz_ele->base_index);
- RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index);
- RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index);
- RNA_int_set(gz->ptr, "face_index", gz_ele->face_index);
+ RNA_int_set(gz->ptr, "object_index", gz_ele->base_index);
+ RNA_int_set(gz->ptr, "vert_index", gz_ele->vert_index);
+ RNA_int_set(gz->ptr, "edge_index", gz_ele->edge_index);
+ RNA_int_set(gz->ptr, "face_index", gz_ele->face_index);
+ if (best.ele) {
ARegion *ar = CTX_wm_region(C);
ED_region_tag_redraw(ar);
}
@@ -471,5 +504,4 @@ void ED_view3d_gizmo_mesh_preselect_get_active(bContext *C,
}
}
}
-
/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
index 97a12c7100e..f4e3dc85447 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_ruler.c
@@ -343,6 +343,7 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
.use_object_edit_cage = true,
},
mval_fl,
+ NULL,
&dist_px,
co,
ray_normal)) {
@@ -363,16 +364,31 @@ static bool view3d_ruler_item_mousemove(RulerInfo *ruler_info,
}
else if (do_snap) {
const float mval_fl[2] = {UNPACK2(mval)};
+ float *prev_point = NULL;
+
+ if (inter->co_index != 1) {
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ prev_point = ruler_item->co[1];
+ }
+ else if (inter->co_index == 0) {
+ prev_point = ruler_item->co[2];
+ }
+ else {
+ prev_point = ruler_item->co[0];
+ }
+ }
if (ED_transform_snap_object_project_view3d(
ruler_info->snap_context,
- (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE),
+ (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
+ SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR),
&(const struct SnapObjectParams){
.snap_select = SNAP_ALL,
.use_object_edit_cage = true,
.use_occlusion_test = true,
},
mval_fl,
+ prev_point,
&dist_px,
co,
NULL)) {
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 3a6825aacb4..6b5c27b68f4 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -30,18 +30,11 @@
struct ARegion;
struct ARegionType;
-struct Base;
struct BoundBox;
struct Depsgraph;
-struct GPUBatch;
-struct Mesh;
struct Object;
-struct SmokeDomainSettings;
struct ViewLayer;
-struct bAnimVizSettings;
struct bContext;
-struct bMotionPath;
-struct bPoseChannel;
struct wmGizmoGroupType;
struct wmGizmoType;
struct wmKeyConfig;
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 725f655c8ce..1c9ce142165 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -88,6 +88,7 @@
#include "ED_particle.h"
#include "ED_mesh.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
#include "ED_sculpt.h"
@@ -1280,9 +1281,15 @@ static bool view3d_lasso_select(
}
else if (ob && (ob->mode & OB_MODE_POSE)) {
changed_multi |= do_lasso_select_pose(vc, mcords, moves, sel_op);
+ if (changed_multi) {
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+ }
}
else {
changed_multi |= do_lasso_select_objects(vc, mcords, moves, sel_op);
+ if (changed_multi) {
+ ED_outliner_select_sync_from_object_tag(C);
+ }
}
}
else { /* Edit Mode */
@@ -1303,12 +1310,15 @@ static bool view3d_lasso_select(
break;
case OB_ARMATURE:
changed = do_lasso_select_armature(vc, mcords, moves, sel_op);
+ if (changed) {
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+ }
break;
case OB_MBALL:
changed = do_lasso_select_meta(vc, mcords, moves, sel_op);
break;
default:
- assert(!"lasso select on incorrect object type");
+ BLI_assert(!"lasso select on incorrect object type");
break;
}
@@ -1488,6 +1498,9 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
+
+ ED_outliner_select_sync_from_object_tag(C);
+
return OPERATOR_FINISHED;
}
else {
@@ -2350,6 +2363,9 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
if (!retval && deselect_all) {
retval = ED_armature_edit_deselect_all_visible_multi(C);
}
+ if (retval) {
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+ }
}
else if (obedit->type == OB_LATTICE) {
retval = ED_lattice_select_pick(C, location, extend, deselect, toggle);
@@ -2410,6 +2426,15 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
DEG_id_tag_update(&scene->id, ID_RECALC_SELECT);
}
}
+
+ if (retval) {
+ if (obact && obact->mode & OB_MODE_POSE) {
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+ }
+ else {
+ ED_outliner_select_sync_from_object_tag(C);
+ }
+ }
}
/* Pass-through allows tweaks
@@ -3230,6 +3255,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
if (changed) {
DEG_id_tag_update(&vc.obedit->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
+ ED_outliner_select_sync_from_edit_bone_tag(C);
}
break;
case OB_LATTICE:
@@ -3240,7 +3266,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
}
break;
default:
- assert(!"box select on incorrect object type");
+ BLI_assert(!"box select on incorrect object type");
break;
}
changed_multi |= changed;
@@ -3264,9 +3290,15 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
}
else if (vc.obact && vc.obact->mode & OB_MODE_POSE) {
changed_multi = do_pose_box_select(C, &vc, &rect, sel_op);
+ if (changed_multi) {
+ ED_outliner_select_sync_from_pose_bone_tag(C);
+ }
}
else { /* object mode with none active */
changed_multi = do_object_box_select(C, &vc, &rect, sel_op);
+ if (changed_multi) {
+ ED_outliner_select_sync_from_object_tag(C);
+ }
}
}
@@ -3890,7 +3922,8 @@ static bool mball_circle_select(ViewContext *vc,
/** Callbacks for circle selection in Editmode */
-static bool obedit_circle_select(ViewContext *vc,
+static bool obedit_circle_select(bContext *C,
+ ViewContext *vc,
wmGenericUserData *wm_userdata,
const eSelectOp sel_op,
const int mval[2],
@@ -3911,6 +3944,9 @@ static bool obedit_circle_select(ViewContext *vc,
break;
case OB_ARMATURE:
changed = armature_circle_select(vc, sel_op, mval, rad);
+ if (changed) {
+ ED_outliner_select_sync_from_edit_bone_tag(C);
+ }
break;
case OB_MBALL:
changed = mball_circle_select(vc, sel_op, mval, rad);
@@ -3999,7 +4035,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
obedit = vc.obedit;
if (obedit) {
- obedit_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius);
+ obedit_circle_select(C, &vc, wm_userdata, sel_op, mval, (float)radius);
}
else if (BKE_paint_select_face_test(obact)) {
paint_facesel_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius);
@@ -4009,6 +4045,7 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
}
else if (obact->mode & OB_MODE_POSE) {
pose_circle_select(&vc, sel_op, mval, (float)radius);
+ ED_outliner_select_sync_from_pose_bone_tag(C);
}
else {
BLI_assert(0);
@@ -4029,6 +4066,8 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
if (object_circle_select(&vc, sel_op, mval, (float)radius)) {
DEG_id_tag_update(&vc.scene->id, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
+
+ ED_outliner_select_sync_from_object_tag(C);
}
}
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 7f930f1d876..1af94e3ade5 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -622,8 +622,8 @@ bool ED_view3d_camera_autokey(
/**
* Call after modifying a locked view.
*
- * \note Not every view edit currently auto-keys (numpad for eg),
- * this is complicated because of smoothview.
+ * \note Not every view edit currently auto-keys (num-pad for eg),
+ * this is complicated because of smooth-view.
*/
bool ED_view3d_camera_lock_autokey(View3D *v3d,
RegionView3D *rv3d,
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 14995144c5c..c344b6c8649 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -3520,7 +3520,7 @@ static void initShear_mouseInputMode(TransInfo *t)
copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]);
}
else {
- cross_v3_v3v3(dir, t->orient_matrix[t->orient_axis_ortho], t->orient_matrix[t->orient_axis]);
+ cross_v3_v3v3(dir, t->orient_matrix[t->orient_axis], t->orient_matrix[t->orient_axis_ortho]);
}
/* Without this, half the gizmo handles move in the opposite direction. */
@@ -6601,7 +6601,7 @@ static void slide_origdata_interp_data_vert(SlideOrigData *sod,
* and we do not want to mess up other shape keys */
BM_loop_interp_from_face(bm, l, f_copy, false, false);
- /* make sure face-attributes are correct (e.g. MTexPoly) */
+ /* make sure face-attributes are correct (e.g. #MLoopUV, #MLoopCol) */
BM_elem_attrs_copy_ex(sod->bm_origfaces, bm, f_copy, l->f, 0x0, CD_MASK_NORMAL);
/* weight the loop */
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index b023199fa1b..45efde24d83 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -42,7 +42,6 @@ struct EditBone;
struct NumInput;
struct Object;
struct RNG;
-struct RenderEngineType;
struct ReportList;
struct Scene;
struct ScrArea;
@@ -52,7 +51,6 @@ struct TransDataContainer;
struct TransInfo;
struct TransSnap;
struct TransformOrientation;
-struct View3D;
struct ViewLayer;
struct bConstraint;
struct bContext;
@@ -85,7 +83,9 @@ typedef struct TransSnap {
bool snap_self;
bool peel;
bool snap_spatial_grid;
- short status;
+ char status;
+ /* Snapped Element Type (currently for objects only). */
+ char snapElem;
/** snapping from this point (in global-space). */
float snapPoint[3];
/** to this point (in global-space). */
@@ -375,6 +375,7 @@ typedef struct VertSlideParams {
typedef struct BoneInitData {
struct EditBone *bone;
float tail[3];
+ float rad_head;
float rad_tail;
float roll;
float head[3];
@@ -1164,4 +1165,7 @@ bool checkUseAxisMatrix(TransInfo *t);
th != tc_end; \
th++, i++)
+void trans_obdata_in_obmode_update_all(struct TransInfo *t);
+void trans_obchild_in_obmode_update_all(struct TransInfo *t);
+
#endif
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index ef9d23d1db8..611992c1d3c 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -52,6 +52,7 @@
#include "BLI_string.h"
#include "BLI_bitmap.h"
#include "BLI_rect.h"
+#include "BLI_kdtree.h"
#include "BKE_action.h"
#include "BKE_animsys.h"
@@ -235,8 +236,9 @@ static void sort_trans_data_selected_first(TransInfo *t)
}
}
-/* distance calculated from not-selected vertex to nearest selected vertex
- * warning; this is loops inside loop, has minor N^2 issues, but by sorting list it is OK */
+/**
+ * Distance calculated from not-selected vertex to nearest selected vertex.
+ */
static void set_prop_dist(TransInfo *t, const bool with_dist)
{
int a;
@@ -255,54 +257,124 @@ static void set_prop_dist(TransInfo *t, const bool with_dist)
}
}
+ /* Count number of selected. */
+ int td_table_len = 0;
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
- TransData *tob = tc->data;
- for (a = 0; a < tc->data_len; a++, tob++) {
+ TransData *td = tc->data;
+ for (a = 0; a < tc->data_len; a++, td++) {
+ if (td->flag & TD_SELECTED) {
+ td_table_len++;
+ }
+ else {
+ /* By definition transform-data has selected items in beginning. */
+ break;
+ }
+ }
+ }
- tob->rdist = 0.0f; // init, it was mallocced
+ /* Pointers to selected's #TransData.
+ * Used to find #TransData from the index returned by #BLI_kdtree_find_nearest. */
+ TransData **td_table = MEM_mallocN(sizeof(*td_table) * td_table_len, __func__);
- if ((tob->flag & TD_SELECTED) == 0) {
- TransData *td;
- int i;
- float dist_sq, vec[3];
+ /* Create and fill kd-tree of selected's positions - in global or proj_vec space. */
+ KDTree_3d *td_tree = BLI_kdtree_3d_new(td_table_len);
- tob->rdist = -1.0f; // signal for next loop
+ int td_table_index = 0;
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (a = 0; a < tc->data_len; a++, td++) {
+ if (td->flag & TD_SELECTED) {
+ /* Initialize, it was mallocced. */
+ float vec[3];
+ td->rdist = 0.0f;
+
+ if (use_island) {
+ if (tc->use_local_mat) {
+ mul_v3_m4v3(vec, tc->mat, td->iloc);
+ }
+ else {
+ mul_v3_m3v3(vec, td->mtx, td->iloc);
+ }
+ }
+ else {
+ if (tc->use_local_mat) {
+ mul_v3_m4v3(vec, tc->mat, td->center);
+ }
+ else {
+ mul_v3_m3v3(vec, td->mtx, td->center);
+ }
+ }
- for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
- if (td->flag & TD_SELECTED) {
- if (use_island) {
- sub_v3_v3v3(vec, tob->iloc, td->iloc);
- }
- else {
- sub_v3_v3v3(vec, tob->center, td->center);
- }
- mul_m3_v3(tob->mtx, vec);
+ if (proj_vec) {
+ float vec_p[3];
+ project_v3_v3v3(vec_p, vec, proj_vec);
+ sub_v3_v3(vec, vec_p);
+ }
- if (proj_vec) {
- float vec_p[3];
- project_v3_v3v3(vec_p, vec, proj_vec);
- sub_v3_v3(vec, vec_p);
- }
+ BLI_kdtree_3d_insert(td_tree, td_table_index, vec);
+ td_table[td_table_index++] = td;
+ }
+ else {
+ /* By definition transform-data has selected items in beginning. */
+ break;
+ }
+ }
+ }
+ BLI_assert(td_table_index == td_table_len);
- dist_sq = len_squared_v3(vec);
- if ((tob->rdist == -1.0f) || (dist_sq < SQUARE(tob->rdist))) {
- tob->rdist = sqrtf(dist_sq);
- if (use_island) {
- copy_v3_v3(tob->center, td->center);
- copy_m3_m3(tob->axismtx, td->axismtx);
- }
- }
+ BLI_kdtree_3d_balance(td_tree);
+
+ /* For each non-selected vertex, find distance to the nearest selected vertex. */
+ FOREACH_TRANS_DATA_CONTAINER (t, tc) {
+ TransData *td = tc->data;
+ for (a = 0; a < tc->data_len; a++, td++) {
+ if ((td->flag & TD_SELECTED) == 0) {
+ float vec[3];
+
+ if (use_island) {
+ if (tc->use_local_mat) {
+ mul_v3_m4v3(vec, tc->mat, td->iloc);
}
else {
- break; /* by definition transdata has selected items in beginning */
+ mul_v3_m3v3(vec, td->mtx, td->iloc);
}
}
+ else {
+ if (tc->use_local_mat) {
+ mul_v3_m4v3(vec, tc->mat, td->center);
+ }
+ else {
+ mul_v3_m3v3(vec, td->mtx, td->center);
+ }
+ }
+
+ if (proj_vec) {
+ float vec_p[3];
+ project_v3_v3v3(vec_p, vec, proj_vec);
+ sub_v3_v3(vec, vec_p);
+ }
+
+ KDTreeNearest_3d nearest;
+ const int td_index = BLI_kdtree_3d_find_nearest(td_tree, vec, &nearest);
+
+ td->rdist = -1.0f;
+ if (td_index != -1) {
+ td->rdist = nearest.dist;
+ if (use_island) {
+ copy_v3_v3(td->center, td_table[td_index]->center);
+ copy_m3_m3(td->axismtx, td_table[td_index]->axismtx);
+ }
+ }
+
if (with_dist) {
- tob->dist = tob->rdist;
+ td->dist = td->rdist;
}
}
}
}
+
+ BLI_kdtree_3d_free(td_tree);
+ MEM_freeN(td_table);
}
/* ************************** CONVERSIONS ************************* */
@@ -1445,6 +1517,7 @@ void restoreBones(TransDataContainer *tc)
ebo = bid->bone;
ebo->dist = bid->dist;
+ ebo->rad_head = bid->rad_head;
ebo->rad_tail = bid->rad_tail;
ebo->roll = bid->roll;
ebo->xwidth = bid->xwidth;
@@ -1710,6 +1783,7 @@ static void createTransArmatureVerts(TransInfo *t)
if (eboflip) {
bid[i].bone = eboflip;
bid[i].dist = eboflip->dist;
+ bid[i].rad_head = eboflip->rad_head;
bid[i].rad_tail = eboflip->rad_tail;
bid[i].roll = eboflip->roll;
bid[i].xwidth = eboflip->xwidth;
@@ -6462,11 +6536,14 @@ static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *obje
depsgraph, &object->id, DEG_OB_COMP_TRANSFORM, set_trans_object_base_deps_flag_cb, NULL);
}
-static void trans_object_base_deps_flag_finish(ViewLayer *view_layer)
+static void trans_object_base_deps_flag_finish(const TransInfo *t, ViewLayer *view_layer)
{
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- if (base->object->id.tag & LIB_TAG_DOIT) {
- base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
+
+ if ((t->options & CTX_OBMODE_XFORM_OBDATA) == 0) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->id.tag & LIB_TAG_DOIT) {
+ base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
+ }
}
}
}
@@ -6495,7 +6572,7 @@ static void set_trans_object_base_flags(TransInfo *t)
trans_object_base_deps_flag_prepare(view_layer);
/* Traverse all bases and set all possible flags. */
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- base->flag_legacy &= ~BA_WAS_SEL;
+ base->flag_legacy &= ~(BA_WAS_SEL | BA_TRANSFORM_LOCKED_IN_PLACE);
if (BASE_SELECTED_EDITABLE(v3d, base)) {
Object *ob = base->object;
Object *parsel = ob->parent;
@@ -6528,7 +6605,7 @@ static void set_trans_object_base_flags(TransInfo *t)
/* Store temporary bits in base indicating that base is being modified
* (directly or indirectly) by transforming objects.
*/
- trans_object_base_deps_flag_finish(view_layer);
+ trans_object_base_deps_flag_finish(t, view_layer);
}
static bool mark_children(Object *ob)
@@ -6596,7 +6673,7 @@ static int count_proportional_objects(TransInfo *t)
/* Store temporary bits in base indicating that base is being modified
* (directly or indirectly) by transforming objects.
*/
- trans_object_base_deps_flag_finish(view_layer);
+ trans_object_base_deps_flag_finish(t, view_layer);
return total;
}
@@ -6611,7 +6688,8 @@ static void clear_trans_object_base_flags(TransInfo *t)
}
base->flag_legacy &= ~(BA_WAS_SEL | BA_SNAP_FIX_DEPS_FIASCO | BA_TEMP_TAG |
- BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT);
+ BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT |
+ BA_TRANSFORM_LOCKED_IN_PLACE);
}
}
@@ -7049,7 +7127,15 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t)
hflag = BM_ELEM_SELECT;
}
- EDBM_automerge(t->scene, tc->obedit, true, hflag);
+ if (t->scene->toolsettings->automerge & AUTO_MERGE) {
+ if (t->scene->toolsettings->automerge & AUTO_MERGE_AND_SPLIT) {
+ EDBM_automerge_and_split(
+ tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit);
+ }
+ else {
+ EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit);
+ }
+ }
/* Special case, this is needed or faces won't re-select.
* Flush selected edges to faces. */
@@ -7433,7 +7519,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
else if (t->flag & T_POSE && (t->mode == TFM_BONESIZE)) {
/* Handle the exception where for TFM_BONESIZE in edit mode we pretend to be
* in pose mode (to use bone orientation matrix),
- * in that case we don't do operations like autokeyframing. */
+ * in that case we don't do operations like auto-keyframing. */
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
ob = tc->poseobj;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@@ -7604,6 +7690,278 @@ int special_transform_moving(TransInfo *t)
return 0;
}
+/* -------------------------------------------------------------------- */
+/** \name Object Mode Custom Data
+ * \{ */
+
+typedef struct TransDataObject {
+
+ /**
+ * Object to object data transform table.
+ * Don't add these to transform data because we may want to include child objects
+ * which aren't being transformed.
+ * - The key is object data #ID.
+ * - The value is #XFormObjectData_Extra.
+ */
+ struct GHash *obdata_in_obmode_map;
+
+ /**
+ * Transform
+ * - The key is object data #Object.
+ * - The value is #XFormObjectSkipChild.
+ */
+ struct GHash *obchild_in_obmode_map;
+
+} TransDataObject;
+
+/** \} */
+
+static void trans_obdata_in_obmode_free_all(TransDataObject *tdo);
+static void trans_obchild_in_obmode_free_all(TransDataObject *tdo);
+
+static void freeTransObjectCustomData(TransInfo *t,
+ TransDataContainer *UNUSED(tc),
+ TransCustomData *custom_data)
+{
+ TransDataObject *tdo = custom_data->data;
+ custom_data->data = NULL;
+
+ if (t->options & CTX_OBMODE_XFORM_OBDATA) {
+ trans_obdata_in_obmode_free_all(tdo);
+ }
+
+ if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) {
+ trans_obchild_in_obmode_free_all(tdo);
+ }
+ MEM_freeN(tdo);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Data in Object Mode
+ *
+ * Use to implement 'Affect Only Origins' feature.
+ * We need this to be detached from transform data because,
+ * unlike transforming regular objects, we need to transform the children.
+ *
+ * \{ */
+
+struct XFormObjectData_Extra {
+ Object *ob;
+ float obmat_orig[4][4];
+ struct XFormObjectData *xod;
+};
+
+static void trans_obdata_in_obmode_ensure_object(TransDataObject *tdo, Object *ob)
+{
+ if (tdo->obdata_in_obmode_map == NULL) {
+ tdo->obdata_in_obmode_map = BLI_ghash_ptr_new(__func__);
+ }
+
+ void **xf_p;
+ if (!BLI_ghash_ensure_p(tdo->obdata_in_obmode_map, ob->data, &xf_p)) {
+ struct XFormObjectData_Extra *xf = MEM_mallocN(sizeof(*xf), __func__);
+ copy_m4_m4(xf->obmat_orig, ob->obmat);
+ xf->ob = ob;
+ /* Result may be NULL, that's OK. */
+ xf->xod = ED_object_data_xform_create(ob->data);
+ *xf_p = xf;
+ }
+}
+
+void trans_obdata_in_obmode_update_all(TransInfo *t)
+{
+ TransDataObject *tdo = t->custom.type.data;
+ if (tdo->obdata_in_obmode_map == NULL) {
+ return;
+ }
+
+ struct Main *bmain = CTX_data_main(t->context);
+ BKE_scene_graph_evaluated_ensure(t->depsgraph, bmain);
+
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, tdo->obdata_in_obmode_map) {
+ ID *id = BLI_ghashIterator_getKey(&gh_iter);
+ struct XFormObjectData_Extra *xf = BLI_ghashIterator_getValue(&gh_iter);
+ if (xf->xod == NULL) {
+ continue;
+ }
+
+ Object *ob_eval = DEG_get_evaluated_object(t->depsgraph, xf->ob);
+ float imat[4][4], dmat[4][4];
+ invert_m4_m4(imat, xf->obmat_orig);
+ mul_m4_m4m4(dmat, imat, ob_eval->obmat);
+ invert_m4(dmat);
+
+ ED_object_data_xform_by_mat4(xf->xod, dmat);
+ DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
+ }
+}
+
+/** Callback for #GHash free. */
+static void trans_obdata_in_obmode_free_elem(void *xf_p)
+{
+ struct XFormObjectData_Extra *xf = xf_p;
+ if (xf->xod) {
+ ED_object_data_xform_destroy(xf->xod);
+ }
+ MEM_freeN(xf);
+}
+
+static void trans_obdata_in_obmode_free_all(TransDataObject *tdo)
+{
+ if (tdo->obdata_in_obmode_map != NULL) {
+ BLI_ghash_free(tdo->obdata_in_obmode_map, NULL, trans_obdata_in_obmode_free_elem);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object Child Skip
+ *
+ * Don't transform unselected children, this is done using the parent inverse matrix.
+ *
+ * \note The complex logic here is caused by mixed selection within a single selection chain,
+ * otherwise we only need #OB_SKIP_CHILD_PARENT_IS_XFORM for single objects.
+ *
+ * \{ */
+
+enum {
+ /**
+ * The parent is transformed, this is held in place.
+ */
+ OB_SKIP_CHILD_PARENT_IS_XFORM = 1,
+ /**
+ * The same as #OB_SKIP_CHILD_PARENT_IS_XFORM,
+ * however this objects parent isn't transformed directly.
+ */
+ OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT = 3,
+ /**
+ * Use the parent invert matrix to apply transformation,
+ * this is needed, because breaks in the selection chain prevents this from being transformed.
+ * This is used to add the transform which would have been added
+ * if there weren't breaks in the parent/child chain.
+ */
+ OB_SKIP_CHILD_PARENT_APPLY_TRANSFORM = 2,
+};
+
+struct XFormObjectSkipChild {
+ float obmat_orig[4][4];
+ float parent_obmat_orig[4][4];
+ float parent_obmat_inv_orig[4][4];
+ float parent_recurse_obmat_orig[4][4];
+ float parentinv_orig[4][4];
+ Object *ob_parent_recurse;
+ int mode;
+};
+
+static void trans_obchild_in_obmode_ensure_object(TransDataObject *tdo,
+ Object *ob,
+ Object *ob_parent_recurse,
+ int mode)
+{
+ if (tdo->obchild_in_obmode_map == NULL) {
+ tdo->obchild_in_obmode_map = BLI_ghash_ptr_new(__func__);
+ }
+
+ void **xf_p;
+ if (!BLI_ghash_ensure_p(tdo->obchild_in_obmode_map, ob, &xf_p)) {
+ struct XFormObjectSkipChild *xf = MEM_mallocN(sizeof(*xf), __func__);
+ copy_m4_m4(xf->parentinv_orig, ob->parentinv);
+ copy_m4_m4(xf->obmat_orig, ob->obmat);
+ copy_m4_m4(xf->parent_obmat_orig, ob->parent->obmat);
+ invert_m4_m4(xf->parent_obmat_inv_orig, ob->parent->obmat);
+ if (ob_parent_recurse) {
+ copy_m4_m4(xf->parent_recurse_obmat_orig, ob_parent_recurse->obmat);
+ }
+ xf->mode = mode;
+ xf->ob_parent_recurse = ob_parent_recurse;
+ *xf_p = xf;
+ }
+}
+
+void trans_obchild_in_obmode_update_all(TransInfo *t)
+{
+ TransDataObject *tdo = t->custom.type.data;
+ if (tdo->obchild_in_obmode_map == NULL) {
+ return;
+ }
+
+ struct Main *bmain = CTX_data_main(t->context);
+ BKE_scene_graph_evaluated_ensure(t->depsgraph, bmain);
+
+ GHashIterator gh_iter;
+ GHASH_ITER (gh_iter, tdo->obchild_in_obmode_map) {
+ Object *ob = BLI_ghashIterator_getKey(&gh_iter);
+ struct XFormObjectSkipChild *xf = BLI_ghashIterator_getValue(&gh_iter);
+
+ /* The following blocks below assign 'dmat'. */
+ float dmat[4][4];
+
+ if (xf->mode == OB_SKIP_CHILD_PARENT_IS_XFORM) {
+ /* Parent is transformed, this isn't so compensate. */
+ Object *ob_parent_eval = DEG_get_evaluated_object(t->depsgraph, ob->parent);
+ mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, ob_parent_eval->obmat);
+ invert_m4(dmat);
+ }
+ else if (xf->mode == OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT) {
+ /* Calculate parent matrix (from the root transform). */
+ Object *ob_parent_recurse_eval = DEG_get_evaluated_object(t->depsgraph,
+ xf->ob_parent_recurse);
+ float parent_recurse_obmat_inv[4][4];
+ invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat);
+ mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv);
+ invert_m4(dmat);
+ float parent_obmat_calc[4][4];
+ mul_m4_m4m4(parent_obmat_calc, dmat, xf->parent_obmat_orig);
+
+ /* Apply to the parent inverse matrix. */
+ mul_m4_m4m4(dmat, xf->parent_obmat_inv_orig, parent_obmat_calc);
+ invert_m4(dmat);
+ }
+ else {
+ BLI_assert(xf->mode == OB_SKIP_CHILD_PARENT_APPLY_TRANSFORM);
+ /* Transform this - without transform data. */
+ Object *ob_parent_recurse_eval = DEG_get_evaluated_object(t->depsgraph,
+ xf->ob_parent_recurse);
+ float parent_recurse_obmat_inv[4][4];
+ invert_m4_m4(parent_recurse_obmat_inv, ob_parent_recurse_eval->obmat);
+ mul_m4_m4m4(dmat, xf->parent_recurse_obmat_orig, parent_recurse_obmat_inv);
+ invert_m4(dmat);
+ float obmat_calc[4][4];
+ mul_m4_m4m4(obmat_calc, dmat, xf->obmat_orig);
+ /* obmat_calc is just obmat. */
+
+ /* Get the matrices relative to the parent. */
+ float obmat_parent_relative_orig[4][4];
+ float obmat_parent_relative_calc[4][4];
+ float obmat_parent_relative_inv_orig[4][4];
+
+ mul_m4_m4m4(obmat_parent_relative_orig, xf->parent_obmat_inv_orig, xf->obmat_orig);
+ mul_m4_m4m4(obmat_parent_relative_calc, xf->parent_obmat_inv_orig, obmat_calc);
+ invert_m4_m4(obmat_parent_relative_inv_orig, obmat_parent_relative_orig);
+
+ /* Apply to the parent inverse matrix. */
+ mul_m4_m4m4(dmat, obmat_parent_relative_calc, obmat_parent_relative_inv_orig);
+ }
+
+ mul_m4_m4m4(ob->parentinv, dmat, xf->parentinv_orig);
+
+ DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
+ }
+}
+
+static void trans_obchild_in_obmode_free_all(TransDataObject *tdo)
+{
+ if (tdo->obchild_in_obmode_map != NULL) {
+ BLI_ghash_free(tdo->obchild_in_obmode_map, NULL, MEM_freeN);
+ }
+}
+
+/** \} */
+
static void createTransObject(bContext *C, TransInfo *t)
{
TransData *td = NULL;
@@ -7630,6 +7988,10 @@ static void createTransObject(bContext *C, TransInfo *t)
td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransOb");
tx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), "TransObExtension");
+ TransDataObject *tdo = MEM_callocN(sizeof(*tdo), __func__);
+ t->custom.type.data = tdo;
+ t->custom.type.free_cb = freeTransObjectCustomData;
+
CTX_DATA_BEGIN (C, Base *, base, selected_bases) {
Object *ob = base->object;
@@ -7648,6 +8010,24 @@ static void createTransObject(bContext *C, TransInfo *t)
td->flag |= TD_SKIP;
}
+ if (t->options & CTX_OBMODE_XFORM_OBDATA) {
+ ID *id = ob->data;
+ if (!id || id->lib) {
+ td->flag |= TD_SKIP;
+ }
+ else if (BKE_object_is_in_editmode(ob)) {
+ /* The object could have edit-mode data from another view-layer,
+ * it's such a corner-case it can be skipped for now - Campbell. */
+ td->flag |= TD_SKIP;
+ }
+ }
+
+ if (t->options & CTX_OBMODE_XFORM_OBDATA) {
+ if ((td->flag & TD_SKIP) == 0) {
+ trans_obdata_in_obmode_ensure_object(tdo, ob);
+ }
+ }
+
ObjectToTransData(t, td, ob);
td->val = NULL;
td++;
@@ -7679,6 +8059,123 @@ static void createTransObject(bContext *C, TransInfo *t)
}
}
}
+
+ if (t->options & CTX_OBMODE_XFORM_OBDATA) {
+ GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, tc->data_len);
+ td = tc->data;
+ for (int i = 0; i < tc->data_len; i++, td++) {
+ if ((td->flag & TD_SKIP) == 0) {
+ BLI_gset_add(objects_in_transdata, td->ob);
+ }
+ }
+
+ ViewLayer *view_layer = t->view_layer;
+ View3D *v3d = t->view;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+
+ /* if base is not selected, not a parent of selection
+ * or not a child of selection and it is editable and selectable */
+ if ((base->flag_legacy & BA_WAS_SEL) && (base->flag & BASE_SELECTED) == 0 &&
+ BASE_EDITABLE(v3d, base) && BASE_SELECTABLE(v3d, base)) {
+
+ Object *ob_parent = ob->parent;
+ if (ob_parent != NULL) {
+ if (!BLI_gset_haskey(objects_in_transdata, ob)) {
+ bool parent_in_transdata = false;
+ while (ob_parent != NULL) {
+ if (BLI_gset_haskey(objects_in_transdata, ob_parent)) {
+ parent_in_transdata = true;
+ break;
+ }
+ ob_parent = ob_parent->parent;
+ }
+ if (parent_in_transdata) {
+ trans_obdata_in_obmode_ensure_object(tdo, ob);
+ }
+ }
+ }
+ }
+ }
+ BLI_gset_free(objects_in_transdata, NULL);
+ }
+
+ if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) {
+
+#define BASE_XFORM_INDIRECT(base) \
+ ((base->flag_legacy & BA_WAS_SEL) && (base->flag & BASE_SELECTED) == 0)
+
+ GSet *objects_in_transdata = BLI_gset_ptr_new_ex(__func__, tc->data_len);
+ GHash *objects_parent_root = BLI_ghash_ptr_new_ex(__func__, tc->data_len);
+ td = tc->data;
+ for (int i = 0; i < tc->data_len; i++, td++) {
+ if ((td->flag & TD_SKIP) == 0) {
+ BLI_gset_add(objects_in_transdata, td->ob);
+ }
+ }
+
+ ViewLayer *view_layer = t->view_layer;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ if (ob->parent != NULL) {
+ if (ob->parent && !BLI_gset_haskey(objects_in_transdata, ob->parent) &&
+ !BLI_gset_haskey(objects_in_transdata, ob)) {
+ if (((base->flag_legacy & BA_WAS_SEL) && (base->flag & BASE_SELECTED) == 0)) {
+ Base *base_parent = BKE_view_layer_base_find(view_layer, ob->parent);
+ if (base_parent && !BASE_XFORM_INDIRECT(base_parent)) {
+ Object *ob_parent_recurse = ob->parent;
+ if (ob_parent_recurse != NULL) {
+ while (ob_parent_recurse != NULL) {
+ if (BLI_gset_haskey(objects_in_transdata, ob_parent_recurse)) {
+ break;
+ }
+ ob_parent_recurse = ob_parent_recurse->parent;
+ }
+
+ if (ob_parent_recurse) {
+ trans_obchild_in_obmode_ensure_object(
+ tdo, ob, ob_parent_recurse, OB_SKIP_CHILD_PARENT_APPLY_TRANSFORM);
+ BLI_ghash_insert(objects_parent_root, ob, ob_parent_recurse);
+ base->flag_legacy |= BA_TRANSFORM_LOCKED_IN_PLACE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+
+ if (BASE_XFORM_INDIRECT(base) || BLI_gset_haskey(objects_in_transdata, ob)) {
+ /* pass. */
+ }
+ else if (ob->parent != NULL) {
+ Base *base_parent = BKE_view_layer_base_find(view_layer, ob->parent);
+ if (base_parent) {
+ if (BASE_XFORM_INDIRECT(base_parent) ||
+ BLI_gset_haskey(objects_in_transdata, ob->parent)) {
+ trans_obchild_in_obmode_ensure_object(tdo, ob, NULL, OB_SKIP_CHILD_PARENT_IS_XFORM);
+ base->flag_legacy |= BA_TRANSFORM_LOCKED_IN_PLACE;
+ }
+ else {
+ Object *ob_parent_recurse = BLI_ghash_lookup(objects_parent_root, ob->parent);
+ if (ob_parent_recurse) {
+ trans_obchild_in_obmode_ensure_object(
+ tdo, ob, ob_parent_recurse, OB_SKIP_CHILD_PARENT_IS_XFORM_INDIRECT);
+ }
+ }
+ }
+ }
+ }
+ BLI_gset_free(objects_in_transdata, NULL);
+ BLI_ghash_free(objects_parent_root, NULL, NULL);
+
+#undef BASE_XFORM_INDIRECT
+ }
}
/* transcribe given node into TransData2D for Transforming */
@@ -9665,6 +10162,13 @@ void createTransData(bContext *C, TransInfo *t)
/* Needed for correct Object.obmat after duplication, see: T62135. */
BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context));
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) != 0) {
+ t->options |= CTX_OBMODE_XFORM_OBDATA;
+ }
+ if ((scene->toolsettings->transform_flag & SCE_XFORM_SKIP_CHILDREN) != 0) {
+ t->options |= CTX_OBMODE_XFORM_SKIP_CHILDREN;
+ }
+
createTransObject(C, t);
countAndCleanTransDataContainer(t);
t->flag |= T_OBJECT;
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index 969e2558abb..7ae140e1815 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -81,6 +81,7 @@
#include "BKE_workspace.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "ED_anim_api.h"
#include "ED_armature.h"
@@ -900,7 +901,7 @@ static void recalcData_objects(TransInfo *t)
DEG_id_tag_update(tc->obedit->data, 0); /* sets recalc flags */
BMEditMesh *em = BKE_editmesh_from_object(tc->obedit);
EDBM_mesh_normals_update(em);
- BKE_editmesh_tessface_calc(em);
+ BKE_editmesh_looptri_calc(em);
}
}
else if (t->obedit_type == OB_ARMATURE) { /* no recalc flag, does pose */
@@ -1149,6 +1150,14 @@ static void recalcData_objects(TransInfo *t)
/* Update motion paths once for all transformed objects. */
ED_objects_recalculate_paths(t->context, t->scene, true);
}
+
+ if (t->options & CTX_OBMODE_XFORM_SKIP_CHILDREN) {
+ trans_obchild_in_obmode_update_all(t);
+ }
+
+ if (t->options & CTX_OBMODE_XFORM_OBDATA) {
+ trans_obdata_in_obmode_update_all(t);
+ }
}
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index fbfeb4f53de..355cf139abf 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -1392,7 +1392,8 @@ void drawDial3d(const TransInfo *t)
scale *= ED_view3d_pixel_size_no_ui_scale(t->ar->regiondata, mat_final[3]);
mul_mat3_m4_fl(mat_final, scale);
- if ((t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)) && activeSnap(t)) {
+ if (activeSnap(t) && (!transformModeUseSnap(t) ||
+ (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) {
increment = (t->modifiers & MOD_PRECISION) ? t->snap[2] : t->snap[1];
}
else {
diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c
index 6ebed88878f..e771fe43bd8 100644
--- a/source/blender/editors/transform/transform_input.c
+++ b/source/blender/editors/transform/transform_input.c
@@ -299,7 +299,7 @@ static void calcSpringFactor(MouseInput *mi)
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
{
- /* incase we allocate a new value */
+ /* In case we allocate a new value. */
void *mi_data_prev = mi->data;
mi->use_virtual_mval = true;
diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c
index f8e33fe70ad..604c5bbc083 100644
--- a/source/blender/editors/transform/transform_ops.c
+++ b/source/blender/editors/transform/transform_ops.c
@@ -139,22 +139,22 @@ const EnumPropertyItem rna_enum_transform_mode_types[] = {
{TFM_CREASE, "CREASE", 0, "Crease", ""},
{TFM_MIRROR, "MIRROR", 0, "Mirror", ""},
{TFM_BONESIZE, "BONE_SIZE", 0, "Bonesize", ""},
- {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone_Envelope", ""},
- {TFM_BONE_ENVELOPE_DIST, "BONE_ENVELOPE_DIST", 0, "Bone_Envelope_Distance", ""},
- {TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve_Shrinkfatten", ""},
- {TFM_MASK_SHRINKFATTEN, "MASK_SHRINKFATTEN", 0, "Mask_Shrinkfatten", ""},
- {TFM_GPENCIL_SHRINKFATTEN, "GPENCIL_SHRINKFATTEN", 0, "GPencil_Shrinkfatten", ""},
- {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone_Roll", ""},
- {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time_Translate", ""},
- {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time_Slide", ""},
- {TFM_TIME_SCALE, "TIME_SCALE", 0, "Time_Scale", ""},
- {TFM_TIME_EXTEND, "TIME_EXTEND", 0, "Time_Extend", ""},
- {TFM_BAKE_TIME, "BAKE_TIME", 0, "Bake_Time", ""},
+ {TFM_BONE_ENVELOPE, "BONE_ENVELOPE", 0, "Bone Envelope", ""},
+ {TFM_BONE_ENVELOPE_DIST, "BONE_ENVELOPE_DIST", 0, "Bone Envelope Distance", ""},
+ {TFM_CURVE_SHRINKFATTEN, "CURVE_SHRINKFATTEN", 0, "Curve Shrinkfatten", ""},
+ {TFM_MASK_SHRINKFATTEN, "MASK_SHRINKFATTEN", 0, "Mask Shrinkfatten", ""},
+ {TFM_GPENCIL_SHRINKFATTEN, "GPENCIL_SHRINKFATTEN", 0, "GPencil Shrinkfatten", ""},
+ {TFM_BONE_ROLL, "BONE_ROLL", 0, "Bone Roll", ""},
+ {TFM_TIME_TRANSLATE, "TIME_TRANSLATE", 0, "Time Translate", ""},
+ {TFM_TIME_SLIDE, "TIME_SLIDE", 0, "Time Slide", ""},
+ {TFM_TIME_SCALE, "TIME_SCALE", 0, "Time Scale", ""},
+ {TFM_TIME_EXTEND, "TIME_EXTEND", 0, "Time Extend", ""},
+ {TFM_BAKE_TIME, "BAKE_TIME", 0, "Bake Time", ""},
{TFM_BWEIGHT, "BWEIGHT", 0, "Bweight", ""},
{TFM_ALIGN, "ALIGN", 0, "Align", ""},
{TFM_EDGE_SLIDE, "EDGESLIDE", 0, "Edge Slide", ""},
{TFM_SEQ_SLIDE, "SEQSLIDE", 0, "Sequence Slide", ""},
- {TFM_GPENCIL_OPACITY, "GPENCIL_OPACITY", 0, "GPencil_Opacity", ""},
+ {TFM_GPENCIL_OPACITY, "GPENCIL_OPACITY", 0, "GPencil Opacity", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -573,7 +573,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags)
if (flags & P_ORIENT_AXIS_ORTHO) {
prop = RNA_def_property(ot->srna, "orient_axis_ortho", PROP_ENUM, PROP_NONE);
RNA_def_property_ui_text(prop, "Axis Ortho", "");
- RNA_def_property_enum_default(prop, 1);
+ RNA_def_property_enum_default(prop, 0);
RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index dbcc6c1b04a..571ce7a6bc2 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -166,7 +166,10 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
activeCol[3] = 192;
if (t->spacetype == SPACE_VIEW3D) {
- if (validSnap(t)) {
+ bool draw_target = (t->tsnap.status & TARGET_INIT) &&
+ (t->scene->toolsettings->snap_mode & SCE_SNAP_MODE_EDGE_PERPENDICULAR);
+
+ if (draw_target || validSnap(t)) {
TransSnapPoint *p;
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float imat[4][4];
@@ -214,6 +217,48 @@ void drawSnapping(const struct bContext *C, TransInfo *t)
immEnd();
}
+ if (draw_target) {
+ /* Draw snapTarget */
+ float targ_co[3], vx[3], vy[3], v1[3], v2[3], v3[3], v4[4];
+ copy_v3_v3(targ_co, t->tsnap.snapTarget);
+ float px_size = 0.75f * size * ED_view3d_pixel_size(rv3d, targ_co);
+
+ mul_v3_v3fl(vx, imat[0], px_size);
+ mul_v3_v3fl(vy, imat[1], px_size);
+
+ add_v3_v3v3(v1, vx, vy);
+ sub_v3_v3v3(v2, vx, vy);
+ negate_v3_v3(v3, v1);
+ negate_v3_v3(v4, v2);
+
+ add_v3_v3(v1, targ_co);
+ add_v3_v3(v2, targ_co);
+ add_v3_v3(v3, targ_co);
+ add_v3_v3(v4, targ_co);
+
+ immUniformColor4ubv(col);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex3fv(pos, v3);
+ immVertex3fv(pos, v1);
+ immVertex3fv(pos, v4);
+ immVertex3fv(pos, v2);
+ immEnd();
+
+ if (t->tsnap.snapElem & SCE_SNAP_MODE_EDGE_PERPENDICULAR) {
+ immUnbindProgram();
+
+ immBindBuiltinProgram(GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR);
+ immUniform1f("dash_width", 6.0f * U.pixelsize);
+ immUniform1f("dash_factor", 1.0f / 4.0f);
+ immUniformColor4ubv(col);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex3fv(pos, targ_co);
+ immVertex3fv(pos, t->tsnap.snapPoint);
+ immEnd();
+ }
+ }
+
immUnbindProgram();
GPU_depth_test(true);
@@ -328,6 +373,7 @@ void applyProject(TransInfo *t)
.use_occlusion_test = false,
},
mval_fl,
+ NULL,
0,
loc,
no)) {
@@ -586,12 +632,18 @@ static void initSnappingMode(TransInfo *t)
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
(obedit_type == -1)) // Object Mode
{
- /* In "Edit Strokes" mode,
- * snap tool can perform snap to selected or active objects (see T49632)
- * TODO: perform self snap in gpencil_strokes */
- t->tsnap.modeSelect = (((t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR)) != 0) ?
- SNAP_ALL :
- SNAP_NOT_SELECTED);
+
+ if (t->options & (CTX_GPENCIL_STROKES | CTX_CURSOR | CTX_OBMODE_XFORM_OBDATA)) {
+ /* In "Edit Strokes" mode,
+ * snap tool can perform snap to selected or active objects (see T49632)
+ * TODO: perform self snap in gpencil_strokes.
+ *
+ * When we're moving the origins, allow snapping onto our own geometry (see T69132). */
+ t->tsnap.modeSelect = SNAP_ALL;
+ }
+ else {
+ t->tsnap.modeSelect = SNAP_NOT_SELECTED;
+ }
}
else {
/* Grid if snap is not possible */
@@ -993,18 +1045,25 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
float no[3];
float mval[2];
bool found = false;
+ short snap_elem = 0;
float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here
mval[0] = t->mval[0];
mval[1] = t->mval[1];
- if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) {
+ if (t->tsnap.mode & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
+ SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
zero_v3(no); /* objects won't set this */
- found = snapObjectsTransform(t, mval, &dist_px, loc, no);
+ snap_elem = snapObjectsTransform(t, mval, &dist_px, loc, no);
+ found = snap_elem != 0;
}
if ((found == false) && (t->tsnap.mode & SCE_SNAP_MODE_VOLUME)) {
found = peelObjectsTransform(
t, mval, (t->settings->snap_flag & SCE_SNAP_PEEL_OBJECT) != 0, loc, no, NULL);
+
+ if (found) {
+ snap_elem = SCE_SNAP_MODE_VOLUME;
+ }
}
if (found == true) {
@@ -1016,6 +1075,8 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
else {
t->tsnap.status &= ~POINT_INIT;
}
+
+ t->tsnap.snapElem = (char)snap_elem;
}
else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) {
if (t->tsnap.mode & SCE_SNAP_MODE_VERTEX) {
@@ -1186,7 +1247,11 @@ static void TargetSnapClosest(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (td = tc->data, i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) {
- struct BoundBox *bb = BKE_object_boundbox_get(td->ob);
+ const BoundBox *bb = NULL;
+
+ if ((t->options & CTX_OBMODE_XFORM_OBDATA) == 0) {
+ bb = BKE_object_boundbox_get(td->ob);
+ }
/* use boundbox if possible */
if (bb) {
@@ -1259,10 +1324,10 @@ static void TargetSnapClosest(TransInfo *t)
}
}
-bool snapObjectsTransform(
+short snapObjectsTransform(
TransInfo *t, const float mval[2], float *dist_px, float r_loc[3], float r_no[3])
{
- return ED_transform_snap_object_project_view3d(
+ return ED_transform_snap_object_project_view3d_ex(
t->tsnap.object_context,
t->scene->toolsettings->snap_mode,
&(const struct SnapObjectParams){
@@ -1271,9 +1336,13 @@ bool snapObjectsTransform(
.use_occlusion_test = t->scene->toolsettings->snap_mode != SCE_SNAP_MODE_FACE,
},
mval,
+ t->tsnap.snapTarget,
dist_px,
r_loc,
- r_no);
+ r_no,
+ NULL,
+ NULL,
+ NULL);
}
/******************** PEELING *********************************/
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 67bd107ab49..d3cf52ce3fd 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -221,22 +221,40 @@ static void iter_snap_objects(SnapObjectContext *sctx,
Base *base_act = view_layer->basact;
for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
- if ((BASE_VISIBLE(v3d, base)) && (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) == 0 &&
- !((snap_select == SNAP_NOT_SELECTED &&
- ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL))) ||
- (snap_select == SNAP_NOT_ACTIVE && base == base_act))) {
- 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_eval);
- for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
- sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
- }
- free_object_duplilist(lb);
+
+ if (!BASE_VISIBLE(v3d, base)) {
+ continue;
+ }
+
+ if (base->flag_legacy & BA_TRANSFORM_LOCKED_IN_PLACE) {
+ /* pass */
+ }
+ else if (base->flag_legacy & BA_SNAP_FIX_DEPS_FIASCO) {
+ continue;
+ }
+
+ if (snap_select == SNAP_NOT_SELECTED) {
+ if ((base->flag & BASE_SELECTED) || (base->flag_legacy & BA_WAS_SEL)) {
+ continue;
+ }
+ }
+ else if (snap_select == SNAP_NOT_ACTIVE) {
+ if (base == base_act) {
+ continue;
}
+ }
- sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
+ 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_eval);
+ for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) {
+ sob_callback(sctx, use_object_edit_cage, dupli_ob->ob, dupli_ob->mat, data);
+ }
+ free_object_duplilist(lb);
}
+
+ sob_callback(sctx, use_object_edit_cage, obj_eval, obj_eval->obmat, data);
}
}
@@ -583,37 +601,31 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
}
if (treedata->tree == NULL) {
- BVHCache **bvh_cache = NULL;
- BLI_bitmap *elem_mask = NULL;
- BMEditMesh *em_orig;
- int looptri_num_active = -1;
-
/* Get original version of the edit_mesh. */
- em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
+ BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
if (sctx->callbacks.edit_mesh.test_face_fn) {
BMesh *bm = em_orig->bm;
BLI_assert(poly_to_tri_count(bm->totface, bm->totloop) == em_orig->tottri);
- elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__);
- looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
+ BLI_bitmap *elem_mask = BLI_BITMAP_NEW(em_orig->tottri, __func__);
+ int looptri_num_active = BM_iter_mesh_bitmap_from_filter_tessface(
bm,
elem_mask,
sctx->callbacks.edit_mesh.test_face_fn,
sctx->callbacks.edit_mesh.user_data);
+
+ bvhtree_from_editmesh_looptri_ex(
+ treedata, em_orig, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL);
+
+ MEM_freeN(elem_mask);
}
else {
/* Only cache if bvhtree is created without a mask.
* This helps keep a standardized bvhtree in cache. */
- bvh_cache = em_bvh_cache;
+ BKE_bvhtree_from_editmesh_get(treedata, em_orig, 4, BVHTREE_FROM_EM_LOOPTRI, em_bvh_cache);
}
- bvhtree_from_editmesh_looptri_ex(
- treedata, em_orig, elem_mask, looptri_num_active, 0.0f, 4, 6, bvh_cache);
-
- if (elem_mask) {
- MEM_freeN(elem_mask);
- }
if (treedata->tree == NULL) {
return retval;
}
@@ -1260,7 +1272,8 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
const MPoly *mp = &((SnapObjectData_Mesh *)sod)->poly[*r_index];
const MLoop *ml = &treedata->loop[mp->loopstart];
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (snapdata->snap_to_flag &
+ (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
elem = SCE_SNAP_MODE_EDGE;
BLI_assert(treedata->edge != NULL);
for (int i = mp->totloop; i--; ml++) {
@@ -1297,7 +1310,8 @@ static short snap_mesh_polygon(SnapObjectContext *sctx,
BMFace *f = BM_face_at_index(em->bm, *r_index);
BMLoop *l_iter, *l_first;
l_iter = l_first = BM_FACE_FIRST_LOOP(f);
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (snapdata->snap_to_flag &
+ (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
elem = SCE_SNAP_MODE_EDGE;
BM_mesh_elem_index_ensure(em->bm, BM_EDGE);
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE);
@@ -1352,6 +1366,7 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
Object *ob,
float obmat[4][4],
float original_dist_px,
+ const float prev_co[3],
/* read/write args */
float *dist_px,
/* return args */
@@ -1420,19 +1435,74 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
&lambda)) {
/* do nothing */
}
- else if (lambda < 0.25f || 0.75f < lambda) {
- int v_id = lambda < 0.5f ? 0 : 1;
+ else {
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_VERTEX) {
+ if (lambda < 0.25f || 0.75f < lambda) {
+ int v_id = lambda < 0.5f ? 0 : 1;
- if (test_projected_vert_dist(&neasrest_precalc,
- NULL,
- 0,
- nearest2d.is_persp,
- v_pair[v_id],
- &nearest.dist_sq,
- nearest.co)) {
- nearest.index = vindex[v_id];
- nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata);
- elem = SCE_SNAP_MODE_VERTEX;
+ if (test_projected_vert_dist(&neasrest_precalc,
+ NULL,
+ 0,
+ nearest2d.is_persp,
+ v_pair[v_id],
+ &nearest.dist_sq,
+ nearest.co)) {
+ nearest.index = vindex[v_id];
+ nearest2d.copy_vert_no(vindex[v_id], nearest.no, nearest2d.userdata);
+ elem = SCE_SNAP_MODE_VERTEX;
+ }
+ }
+ }
+
+ if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE_MIDPOINT) {
+ if (0.375f < lambda && lambda < 0.625f) {
+ float vmid[3];
+ mid_v3_v3v3(vmid, v_pair[0], v_pair[1]);
+
+ if (test_projected_vert_dist(&neasrest_precalc,
+ NULL,
+ 0,
+ nearest2d.is_persp,
+ vmid,
+ &nearest.dist_sq,
+ nearest.co)) {
+ float v_nor[2][3];
+ nearest2d.copy_vert_no(vindex[0], v_nor[0], nearest2d.userdata);
+ nearest2d.copy_vert_no(vindex[1], v_nor[1], nearest2d.userdata);
+ mid_v3_v3v3(nearest.no, v_nor[0], v_nor[1]);
+ nearest.index = *r_index;
+ elem = SCE_SNAP_MODE_EDGE_MIDPOINT;
+ }
+ }
+ }
+
+ if (prev_co && (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
+ float v_near[3], va_g[3], vb_g[3];
+
+ mul_v3_m4v3(va_g, obmat, v_pair[0]);
+ mul_v3_m4v3(vb_g, obmat, v_pair[1]);
+ lambda = line_point_factor_v3(prev_co, va_g, vb_g);
+
+ if (IN_RANGE(lambda, 0.0f, 1.0f)) {
+ interp_v3_v3v3(v_near, va_g, vb_g, lambda);
+
+ if ((len_squared_v3v3(prev_co, v_near) > FLT_EPSILON) &&
+ test_projected_vert_dist(&neasrest_precalc,
+ NULL,
+ 0,
+ nearest2d.is_persp,
+ v_near,
+ &nearest.dist_sq,
+ nearest.co)) {
+ float v_nor[2][3];
+ nearest2d.copy_vert_no(vindex[0], v_nor[0], nearest2d.userdata);
+ nearest2d.copy_vert_no(vindex[1], v_nor[1], nearest2d.userdata);
+ mid_v3_v3v3(nearest.no, v_nor[0], v_nor[1]);
+
+ nearest.index = *r_index;
+ elem = SCE_SNAP_MODE_EDGE_PERPENDICULAR;
+ }
+ }
}
}
@@ -1440,7 +1510,9 @@ static short snap_mesh_edge_verts_mixed(SnapObjectContext *sctx,
*dist_px = sqrtf(nearest.dist_sq);
copy_v3_v3(r_loc, nearest.co);
- mul_m4_v3(obmat, r_loc);
+ if (elem != SCE_SNAP_MODE_EDGE_PERPENDICULAR) {
+ mul_m4_v3(obmat, r_loc);
+ }
if (r_no) {
float imat[4][4];
@@ -1926,13 +1998,13 @@ static short snapMesh(SnapObjectContext *sctx,
{
BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
- if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
- if (me->totedge == 0) {
+ if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_VERTEX) {
+ if (me->totvert == 0) {
return 0;
}
}
else {
- if (me->totvert == 0) {
+ if (me->totedge == 0) {
return 0;
}
}
@@ -2066,7 +2138,8 @@ static short snapMesh(SnapObjectContext *sctx,
last_index = nearest.index;
}
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (snapdata->snap_to_flag &
+ (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
if (bvhtree[0]) {
/* snap to loose edges */
BLI_bvhtree_find_nearest_projected(bvhtree[0],
@@ -2164,13 +2237,13 @@ static short snapEditMesh(SnapObjectContext *sctx,
{
BLI_assert(snapdata->snap_to_flag != SCE_SNAP_MODE_FACE);
- if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_EDGE) {
- if (em->bm->totedge == 0) {
+ if ((snapdata->snap_to_flag & ~SCE_SNAP_MODE_FACE) == SCE_SNAP_MODE_VERTEX) {
+ if (em->bm->totvert == 0) {
return 0;
}
}
else {
- if (em->bm->totvert == 0) {
+ if (em->bm->totedge == 0) {
return 0;
}
}
@@ -2223,16 +2296,17 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_verts_ex(
- treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6);
+ treedata_vert, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL);
MEM_freeN(verts_mask);
}
else {
- bvhtree_from_editmesh_verts(treedata_vert, em, 0.0f, 2, 6, em_bvh_cache);
+ BKE_bvhtree_from_editmesh_get(treedata_vert, em, 2, BVHTREE_FROM_EM_VERTS, em_bvh_cache);
}
}
}
- if (snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (snapdata->snap_to_flag &
+ (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
if (sod->bvh_trees[1] == NULL) {
sod->bvh_trees[1] = BLI_memarena_calloc(sctx->cache.mem_arena, sizeof(**sod->bvh_trees));
}
@@ -2258,11 +2332,11 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_edges_ex(
- treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6);
+ treedata_edge, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL);
MEM_freeN(edges_mask);
}
else {
- bvhtree_from_editmesh_edges(treedata_edge, em, 0.0f, 2, 6, em_bvh_cache);
+ BKE_bvhtree_from_editmesh_get(treedata_edge, em, 2, BVHTREE_FROM_EM_EDGES, em_bvh_cache);
}
}
}
@@ -2279,7 +2353,6 @@ static short snapEditMesh(SnapObjectContext *sctx,
.index = -1,
.dist_sq = dist_px_sq,
};
- int last_index = nearest.index;
short elem = SCE_SNAP_MODE_VERTEX;
float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
@@ -2300,11 +2373,12 @@ static short snapEditMesh(SnapObjectContext *sctx,
&nearest,
cb_snap_vert,
&nearest2d);
-
- last_index = nearest.index;
}
- if (treedata_edge && snapdata->snap_to_flag & SCE_SNAP_MODE_EDGE) {
+ if (treedata_edge && snapdata->snap_to_flag & (SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT |
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
+ int last_index = nearest.index;
+ nearest.index = -1;
BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
BLI_bvhtree_find_nearest_projected(treedata_edge->tree,
lpmat,
@@ -2316,9 +2390,12 @@ static short snapEditMesh(SnapObjectContext *sctx,
cb_snap_edge,
&nearest2d);
- if (last_index != nearest.index) {
+ if (nearest.index != -1) {
elem = SCE_SNAP_MODE_EDGE;
}
+ else {
+ nearest.index = last_index;
+ }
}
if (nearest.index != -1) {
@@ -2700,6 +2777,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
const unsigned short snap_to_flag,
const struct SnapObjectParams *params,
const float mval[2],
+ const float prev_co[3],
float *dist_px,
float r_loc[3],
float r_no[3],
@@ -2707,7 +2785,8 @@ static short transform_snap_context_project_view3d_mixed_impl(
Object **r_ob,
float r_obmat[4][4])
{
- BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE)) !=
+ BLI_assert((snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_FACE |
+ SCE_SNAP_MODE_EDGE_MIDPOINT | SCE_SNAP_MODE_EDGE_PERPENDICULAR)) !=
0);
short retval = 0;
@@ -2733,7 +2812,7 @@ static short transform_snap_context_project_view3d_mixed_impl(
ray_normal,
ray_start,
true)) {
- return false;
+ return 0;
}
float dummy_ray_depth = BVH_RAYCAST_DIST_MAX;
@@ -2746,7 +2825,8 @@ static short transform_snap_context_project_view3d_mixed_impl(
}
}
- if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE)) {
+ if (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE | SCE_SNAP_MODE_EDGE_MIDPOINT |
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR)) {
short elem;
float dist_px_tmp = *dist_px;
@@ -2799,11 +2879,18 @@ static short transform_snap_context_project_view3d_mixed_impl(
retval = elem;
}
- if ((retval == SCE_SNAP_MODE_EDGE) && (snapdata.snap_to_flag & SCE_SNAP_MODE_VERTEX)) {
- retval = snap_mesh_edge_verts_mixed(
- sctx, &snapdata, ob, obmat, *dist_px, &dist_px_tmp, loc, no, &index);
+ if ((retval == SCE_SNAP_MODE_EDGE) &&
+ (snap_to_flag & (SCE_SNAP_MODE_VERTEX | SCE_SNAP_MODE_EDGE_MIDPOINT |
+ SCE_SNAP_MODE_EDGE_PERPENDICULAR))) {
+ elem = snap_mesh_edge_verts_mixed(
+ sctx, &snapdata, ob, obmat, *dist_px, prev_co, &dist_px_tmp, loc, no, &index);
+ }
+
+ if (elem) {
+ retval = elem;
}
+ retval &= snap_to_flag;
*dist_px = dist_px_tmp;
}
@@ -2831,6 +2918,7 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2],
+ const float prev_co[3],
float *dist_px,
float r_loc[3],
float r_no[3],
@@ -2839,7 +2927,7 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
float r_obmat[4][4])
{
return transform_snap_context_project_view3d_mixed_impl(
- sctx, snap_to, params, mval, dist_px, r_loc, r_no, r_index, r_ob, r_obmat) != 0;
+ sctx, snap_to, params, mval, prev_co, dist_px, r_loc, r_no, r_index, r_ob, r_obmat);
}
/**
@@ -2849,6 +2937,7 @@ short ED_transform_snap_object_project_view3d_ex(SnapObjectContext *sctx,
*
* \param sctx: Snap context.
* \param mval: Screenspace coordinate.
+ * \param prev_co: Coordinate for perpendicular point calculation (optional).
* \param dist_px: Maximum distance to snap (in pixels).
* \param r_co: hit location.
* \param r_no: hit normal (optional).
@@ -2858,12 +2947,13 @@ bool ED_transform_snap_object_project_view3d(SnapObjectContext *sctx,
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2],
+ const float prev_co[3],
float *dist_px,
float r_loc[3],
float r_no[3])
{
return ED_transform_snap_object_project_view3d_ex(
- sctx, snap_to, params, mval, dist_px, r_loc, r_no, NULL, NULL, NULL) != 0;
+ sctx, snap_to, params, mval, prev_co, dist_px, r_loc, r_no, NULL, NULL, NULL) != 0;
}
/**
diff --git a/source/blender/editors/undo/ed_undo.c b/source/blender/editors/undo/ed_undo.c
index c84d7539cce..e0f4d1cf465 100644
--- a/source/blender/editors/undo/ed_undo.c
+++ b/source/blender/editors/undo/ed_undo.c
@@ -53,6 +53,7 @@
#include "ED_gpencil.h"
#include "ED_render.h"
#include "ED_object.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_undo.h"
@@ -390,6 +391,8 @@ static int ed_undo_exec(bContext *C, wmOperator *op)
/* Keep button under the cursor active. */
WM_event_add_mousemove(C);
}
+
+ ED_outliner_select_sync_from_all_tag(C);
return ret;
}
@@ -417,6 +420,8 @@ static int ed_redo_exec(bContext *C, wmOperator *op)
/* Keep button under the cursor active. */
WM_event_add_mousemove(C);
}
+
+ ED_outliner_select_sync_from_all_tag(C);
return ret;
}
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index d97714061c0..fe761f65702 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -205,14 +205,14 @@ static void draw_uvs_shadow(SpaceImage *UNUSED(sima),
Object *obedit,
Depsgraph *depsgraph)
{
- Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit);
- Mesh *me = eval_ob->data;
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, obedit);
+ Mesh *me = ob_eval->data;
float col[4];
UI_GetThemeColor4fv(TH_UV_SHADOW, col);
DRW_mesh_batch_cache_validate(me);
GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me);
- DRW_mesh_batch_cache_create_requested(eval_ob, me, scene, false, false);
+ DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false);
if (edges) {
GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UV_UNIFORM_COLOR);
@@ -223,8 +223,8 @@ static void draw_uvs_shadow(SpaceImage *UNUSED(sima),
static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
{
- Object *eval_ob = DEG_get_evaluated_object(depsgraph, ob);
- Mesh *me = eval_ob->data;
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
+ Mesh *me = ob_eval->data;
ToolSettings *ts = scene->toolsettings;
float col[4];
UI_GetThemeColor4fv(TH_UV_SHADOW, col);
@@ -235,7 +235,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
DRW_mesh_batch_cache_validate(me);
GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me);
- DRW_mesh_batch_cache_create_requested(eval_ob, me, scene, false, false);
+ DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false);
GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR);
GPU_batch_uniform_4fv(geom, "color", col);
@@ -246,7 +246,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
MPoly *mpoly = me->mpoly;
uint draw_start = 0;
uint idx = 0;
- bool prev_ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1));
+ bool prev_ma_match = (mpoly->mat_nr == (ob_eval->actcol - 1));
GPU_matrix_bind(geom->interface);
GPU_batch_bind(geom);
@@ -255,7 +255,7 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
* we can use multi draw indirect drawcalls for this.
* (not implemented in GPU module at the time of writing). */
for (int a = 0; a < me->totpoly; a++, mpoly++) {
- bool ma_match = (mpoly->mat_nr == (eval_ob->actcol - 1));
+ bool ma_match = (mpoly->mat_nr == (ob_eval->actcol - 1));
if (ma_match != prev_ma_match) {
if (ma_match == false) {
GPU_batch_draw_advanced(geom, draw_start, idx - draw_start, 0, 0);
@@ -282,13 +282,13 @@ static void draw_uvs_texpaint(Scene *scene, Object *ob, Depsgraph *depsgraph)
static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *depsgraph)
{
GPUBatch *faces, *edges, *verts, *facedots;
- Object *eval_ob = DEG_get_evaluated_object(depsgraph, obedit);
+ Object *ob_eval = DEG_get_evaluated_object(depsgraph, obedit);
const ToolSettings *ts = scene->toolsettings;
float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f};
if (sima->flag & SI_DRAWSHADOW) {
bool is_cage_like_final_meshes = false;
- Mesh *me = (Mesh *)eval_ob->data;
+ Mesh *me = (Mesh *)ob_eval->data;
BMEditMesh *embm = me->edit_mesh;
is_cage_like_final_meshes = embm && embm->mesh_eval_final &&
embm->mesh_eval_final->runtime.is_original;
@@ -300,7 +300,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *
}
}
- uvedit_get_batches(eval_ob, sima, scene, &faces, &edges, &verts, &facedots);
+ uvedit_get_batches(ob_eval, sima, scene, &faces, &edges, &verts, &facedots);
bool interpedges;
bool draw_stretch = (sima->flag & SI_DRAW_STRETCH) != 0;
@@ -367,33 +367,33 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, Object *obedit, Depsgraph *
break;
}
case SI_UVDT_BLACK:
- case SI_UVDT_WHITE: {
- GPU_line_width(1.0f);
- GPU_batch_program_set_builtin(edges, GPU_SHADER_2D_UNIFORM_COLOR);
- if (sima->dt_uv == SI_UVDT_WHITE) {
- GPU_batch_uniform_4f(edges, "color", 1.0f, 1.0f, 1.0f, 1.0f);
- }
- else {
- GPU_batch_uniform_4f(edges, "color", 0.0f, 0.0f, 0.0f, 1.0f);
- }
- GPU_batch_draw(edges);
- break;
- }
+ case SI_UVDT_WHITE:
case SI_UVDT_OUTLINE: {
/* We could modify the vbo's data filling
* instead of modifying the provoking vert. */
glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
- UI_GetThemeColor4fv(TH_WIRE_EDIT, col1);
UI_GetThemeColor4fv(TH_EDGE_SELECT, col2);
GPU_batch_program_set_builtin(
edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES);
- /* Black Outline. */
- GPU_line_width(3.0f);
- GPU_batch_uniform_4f(edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f);
- GPU_batch_uniform_4f(edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f);
- GPU_batch_draw(edges);
+
+ if (sima->dt_uv == SI_UVDT_OUTLINE) {
+ /* Black Outline. */
+ GPU_line_width(3.0f);
+ GPU_batch_uniform_4f(edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f);
+ GPU_batch_uniform_4f(edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f);
+ GPU_batch_draw(edges);
+
+ UI_GetThemeColor4fv(TH_WIRE_EDIT, col1);
+ }
+ else if (sima->dt_uv == SI_UVDT_WHITE) {
+ copy_v4_fl4(col1, 1.0f, 1.0f, 1.0f, 1.0f);
+ }
+ else {
+ copy_v4_fl4(col1, 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
/* Inner Line. Use depth test to insure selection is drawn on top. */
GPU_depth_test(true);
GPU_line_width(1.0f);
diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h
index 3f544ad90d1..7bc6b048585 100644
--- a/source/blender/editors/uvedit/uvedit_intern.h
+++ b/source/blender/editors/uvedit/uvedit_intern.h
@@ -24,7 +24,6 @@
#ifndef __UVEDIT_INTERN_H__
#define __UVEDIT_INTERN_H__
-struct BMEditMesh;
struct BMFace;
struct BMLoop;
struct Image;
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index dcf1d04ffb3..cd7e5f9ba09 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -138,7 +138,7 @@ static int UNUSED_FUNCTION(ED_operator_uvmap_mesh)(bContext *C)
if (ob && ob->type == OB_MESH) {
Mesh *me = ob->data;
- if (CustomData_get_layer(&me->fdata, CD_MTFACE) != NULL) {
+ if (CustomData_get_layer(&me->ldata, CD_MLOOPUV) != NULL) {
return 1;
}
}
diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
index a42a6eba3ff..2d8f40ea5af 100644
--- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c
+++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c
@@ -524,7 +524,7 @@ static ParamHandle *construct_param_handle_subsurfed(Scene *scene,
smd.levels = smd_real->levels;
smd.subdivType = smd_real->subdivType;
- initialDerived = CDDM_from_editbmesh(em, false, false);
+ initialDerived = CDDM_from_editbmesh(em, false);
derivedMesh = subsurf_make_derived_from_derived(
initialDerived, &smd, scene, NULL, SUBSURF_IN_EDIT_MODE);
diff --git a/source/blender/freestyle/FRS_freestyle.h b/source/blender/freestyle/FRS_freestyle.h
index bad279ed9d9..dc8a0c79072 100644
--- a/source/blender/freestyle/FRS_freestyle.h
+++ b/source/blender/freestyle/FRS_freestyle.h
@@ -29,7 +29,6 @@ struct FreestyleConfig;
struct FreestyleLineStyle;
struct Material;
struct Render;
-struct RenderLayer;
struct FreestyleGlobals {
struct Scene *scene;
diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
index 984a2d01a68..98da8e8f6d3 100644
--- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
+++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp
@@ -865,7 +865,7 @@ Object *BlenderStrokeRenderer::NewMesh() const
BLI_snprintf(name, MAX_ID_NAME, "0%08xME", mesh_id);
ob->data = BKE_mesh_add(freestyle_bmain, name);
- Collection *collection_master = BKE_collection_master(freestyle_scene);
+ Collection *collection_master = freestyle_scene->master_collection;
BKE_collection_object_add(freestyle_bmain, collection_master, ob);
DEG_graph_tag_relations_update(freestyle_depsgraph);
diff --git a/source/blender/freestyle/intern/scene_graph/FrsMaterial.h b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h
index c5a87c3baaf..80cd783f164 100644
--- a/source/blender/freestyle/intern/scene_graph/FrsMaterial.h
+++ b/source/blender/freestyle/intern/scene_graph/FrsMaterial.h
@@ -36,14 +36,14 @@ class FrsMaterial {
/*! Default constructor */
inline FrsMaterial();
- /*! Builds a Material from its line, diffuse, ambiant, specular, emissive
+ /*! Builds a Material from its line, diffuse, ambient, specular, emissive
* colors, a shininess coefficient and line color priority.
* \param iLine:
* A 4 element float-array containing the line color.
* \param iDiffuse:
* A 4 element float-array containing the diffuse color.
* \param iAmbiant:
- * A 4 element float-array containing the ambiant color.
+ * A 4 element float-array containing the ambient color.
* \param iSpecular:
* A 4 element float-array containing the specular color.
* \param iEmission:
@@ -159,31 +159,31 @@ class FrsMaterial {
return Specular[3];
}
- /*! Returns the ambiant color as a 4 float array */
+ /*! Returns the ambient color as a 4 float array */
inline const float *ambient() const
{
return Ambient;
}
- /*! Returns the red component of the ambiant color */
+ /*! Returns the red component of the ambient color */
inline const float ambientR() const
{
return Ambient[0];
}
- /*! Returns the green component of the ambiant color */
+ /*! Returns the green component of the ambient color */
inline const float ambientG() const
{
return Ambient[1];
}
- /*! Returns the blue component of the ambiant color */
+ /*! Returns the blue component of the ambient color */
inline const float ambientB() const
{
return Ambient[2];
}
- /*! Returns the alpha component of the ambiant color */
+ /*! Returns the alpha component of the ambient color */
inline const float ambientA() const
{
return Ambient[3];
@@ -267,7 +267,7 @@ class FrsMaterial {
*/
inline void setSpecular(const float r, const float g, const float b, const float a);
- /*! Sets the ambiant color.
+ /*! Sets the ambient color.
* \param r:
* Red component
* \param g:
diff --git a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
index d70794d9b78..f8dd25913c1 100644
--- a/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
+++ b/source/blender/freestyle/intern/scene_graph/IndexedFaceSet.h
@@ -19,7 +19,7 @@
/** \file
* \ingroup freestyle
- * \brief A Set of indexed faces to represent a surfacic object
+ * \brief A Set of indexed faces to represent a surface object
*/
#include <memory.h>
diff --git a/source/blender/freestyle/intern/scene_graph/NodeTransform.h b/source/blender/freestyle/intern/scene_graph/NodeTransform.h
index ddae714f9d4..1118417657f 100644
--- a/source/blender/freestyle/intern/scene_graph/NodeTransform.h
+++ b/source/blender/freestyle/intern/scene_graph/NodeTransform.h
@@ -48,7 +48,7 @@ class NodeTransform : public NodeGroup {
/*! multiplies the current matrix by the x, y, z translation matrix. */
void Translate(real x, real y, real z);
- /*! multiplis the current matrix by a rotation matrix
+ /*! multiplies the current matrix by a rotation matrix
* iAngle
* The rotation angle
* x, y, z
@@ -56,13 +56,13 @@ class NodeTransform : public NodeGroup {
*/
void Rotate(real iAngle, real x, real y, real z);
- /*! multiplys the current matrix by a scaling matrix.
+ /*! multiplies the current matrix by a scaling matrix.
* x, y, z
* The scaling coefficients with respect to the x,y,z axis
*/
void Scale(real x, real y, real z);
- /*! Multiplys the current matrix by iMatrix */
+ /*! Multiplies the current matrix by iMatrix */
void MultiplyMatrix(const Matrix44r &iMatrix);
/*! Sets the current matrix to iMatrix */
diff --git a/source/blender/freestyle/intern/stroke/Curve.h b/source/blender/freestyle/intern/stroke/Curve.h
index 7eadfa830ce..8a233eef4ab 100644
--- a/source/blender/freestyle/intern/stroke/Curve.h
+++ b/source/blender/freestyle/intern/stroke/Curve.h
@@ -56,7 +56,7 @@ using namespace Geometry;
/*! Class to represent a point of a curve.
* A CurvePoint can be any point of a 1D curve (it doesn't have to be a vertex of the curve).
* Any Interface1D is built upon ViewEdges, themselves built upon FEdges. Therefore, a curve is
- * basically a polyline made of a list SVertex. Thus, a CurvePoint is built by lineraly
+ * basically a polyline made of a list SVertex. Thus, a CurvePoint is built by linearly
* interpolating two SVertex. CurvePoint can be used as virtual points while querying 0D
* information along a curve at a given resolution.
*/
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
index c0ecd3bf0eb..72385fd2f2c 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c
@@ -76,9 +76,10 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[])
#undef INIT_GP_TYPE
}
-/* verify if valid layer and pass index */
+/* verify if valid layer, material and pass index */
bool is_stroke_affected_by_modifier(Object *ob,
char *mlayername,
+ char *mmaterialname,
int mpassindex,
int gpl_passindex,
int minpoints,
@@ -86,9 +87,11 @@ bool is_stroke_affected_by_modifier(Object *ob,
bGPDstroke *gps,
bool inv1,
bool inv2,
- bool inv3)
+ bool inv3,
+ bool inv4)
{
- MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, gps->mat_nr + 1);
+ Material *ma = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
+ MaterialGPencilStyle *gp_style = ma->gp_style;
/* omit if filter by layer */
if (mlayername[0] != '\0') {
@@ -103,6 +106,19 @@ bool is_stroke_affected_by_modifier(Object *ob,
}
}
}
+ /* omit if filter by material */
+ if (mmaterialname[0] != '\0') {
+ if (inv4 == false) {
+ if (!STREQ(mmaterialname, ma->id.name + 2)) {
+ return false;
+ }
+ }
+ else {
+ if (STREQ(mmaterialname, ma->id.name + 2)) {
+ return false;
+ }
+ }
+ }
/* verify layer pass */
if (gpl_passindex > 0) {
if (inv3 == false) {
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
index c3dbd341e10..7f00e072cda 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h
@@ -34,6 +34,7 @@ struct bGPDstroke;
bool is_stroke_affected_by_modifier(struct Object *ob,
char *mlayername,
+ char *mmaterialname,
int mpassindex,
int gpl_passindex,
int minpoints,
@@ -41,7 +42,8 @@ bool is_stroke_affected_by_modifier(struct Object *ob,
bGPDstroke *gps,
bool inv1,
bool inv2,
- bool inv3);
+ bool inv3,
+ bool inv4);
float get_modifier_point_weight(struct MDeformVert *dvert, bool inverse, int def_nr);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
index 4297cbb545c..1f2f0554dd5 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c
@@ -155,7 +155,11 @@ static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
{
ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)md;
- return !mmd->object;
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the armature is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch. */
+ return !mmd->object || mmd->object->type != OB_ARMATURE;
}
static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
index 0a391a6e63e..c311497ffbb 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c
@@ -171,6 +171,7 @@ static void generate_geometry(GpencilModifierData *md,
*/
if (is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
1,
@@ -178,7 +179,8 @@ static void generate_geometry(GpencilModifierData *md,
gps,
mmd->flag & GP_ARRAY_INVERT_LAYER,
mmd->flag & GP_ARRAY_INVERT_PASS,
- mmd->flag & GP_ARRAY_INVERT_LAYERPASS)) {
+ mmd->flag & GP_ARRAY_INVERT_LAYERPASS,
+ mmd->flag & GP_ARRAY_INVERT_MATERIAL)) {
valid_strokes[idx] = true;
num_valid++;
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
index 13329e4176d..cb429b874a2 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c
@@ -51,6 +51,7 @@ static void initData(GpencilModifierData *md)
gpmd->pass_index = 0;
ARRAY_SET_ITEMS(gpmd->hsv, 0.5f, 1.0f, 1.0f);
gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
gpmd->flag |= GP_COLOR_CREATE_COLORS;
gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
}
@@ -74,6 +75,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
1,
@@ -81,7 +83,8 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_COLOR_INVERT_LAYER,
mmd->flag & GP_COLOR_INVERT_PASS,
- mmd->flag & GP_COLOR_INVERT_LAYERPASS)) {
+ mmd->flag & GP_COLOR_INVERT_LAYERPASS,
+ mmd->flag & GP_COLOR_INVERT_MATERIAL)) {
return;
}
@@ -116,7 +119,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
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);
+ Material *mat = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
if (mat == NULL) {
continue;
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
index a3dbcdf23de..810a2ba7e25 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c
@@ -77,6 +77,7 @@ static void initData(GpencilModifierData *md)
HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md;
gpmd->pass_index = 0;
gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
gpmd->object = NULL;
gpmd->force = 0.5f;
@@ -206,6 +207,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
1,
@@ -213,7 +215,8 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_HOOK_INVERT_LAYER,
mmd->flag & GP_HOOK_INVERT_PASS,
- mmd->flag & GP_HOOK_INVERT_LAYERPASS)) {
+ mmd->flag & GP_HOOK_INVERT_LAYERPASS,
+ mmd->flag & GP_HOOK_INVERT_MATERIAL)) {
return;
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
index aa5015bac35..6b74f96ce31 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c
@@ -55,6 +55,7 @@ static void initData(GpencilModifierData *md)
LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md;
gpmd->pass_index = 0;
gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
gpmd->object = NULL;
gpmd->cache_data = NULL;
@@ -78,6 +79,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
1,
@@ -85,7 +87,8 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_LATTICE_INVERT_LAYER,
mmd->flag & GP_LATTICE_INVERT_PASS,
- mmd->flag & GP_LATTICE_INVERT_LAYERPASS)) {
+ mmd->flag & GP_LATTICE_INVERT_LAYERPASS,
+ mmd->flag & GP_LATTICE_INVERT_MATERIAL)) {
return;
}
@@ -166,7 +169,12 @@ static bool isDisabled(GpencilModifierData *md, int UNUSED(userRenderParams))
{
LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md;
- return !mmd->object;
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the lattice is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ return !mmd->object || mmd->object->type != OB_LATTICE;
}
static void updateDepsgraph(GpencilModifierData *md, const ModifierUpdateDepsgraphContext *ctx)
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
index 058f60a69ac..112dfc2e9dc 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c
@@ -57,6 +57,7 @@ static void initData(GpencilModifierData *md)
MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md;
gpmd->pass_index = 0;
gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
gpmd->object = NULL;
gpmd->flag |= GP_MIRROR_AXIS_X;
}
@@ -134,6 +135,7 @@ static void generateStrokes(GpencilModifierData *md,
for (i = 0, gps = gpf->strokes.first; i < tot_strokes; i++, gps = gps->next) {
if (is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
1,
@@ -141,7 +143,8 @@ static void generateStrokes(GpencilModifierData *md,
gps,
mmd->flag & GP_MIRROR_INVERT_LAYER,
mmd->flag & GP_MIRROR_INVERT_PASS,
- mmd->flag & GP_MIRROR_INVERT_LAYERPASS)) {
+ mmd->flag & GP_MIRROR_INVERT_LAYERPASS,
+ mmd->flag & GP_MIRROR_INVERT_MATERIAL)) {
gps_new = BKE_gpencil_stroke_duplicate(gps);
update_position(ob, mmd, gps_new, xi);
BLI_addtail(&gpf->strokes, gps_new);
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
index 2c4d99adeee..b286b55829e 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c
@@ -55,6 +55,7 @@ static void initData(GpencilModifierData *md)
gpmd->flag |= GP_NOISE_USE_RANDOM;
gpmd->factor = 0.5f;
gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
gpmd->step = 1;
gpmd->seed = 0;
@@ -92,6 +93,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
1,
@@ -99,7 +101,8 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_NOISE_INVERT_LAYER,
mmd->flag & GP_NOISE_INVERT_PASS,
- mmd->flag & GP_NOISE_INVERT_LAYERPASS)) {
+ mmd->flag & GP_NOISE_INVERT_LAYERPASS,
+ mmd->flag & GP_NOISE_INVERT_MATERIAL)) {
return;
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
index 399fc407455..08f67eedc86 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c
@@ -48,6 +48,7 @@ static void initData(GpencilModifierData *md)
OffsetGpencilModifierData *gpmd = (OffsetGpencilModifierData *)md;
gpmd->pass_index = 0;
gpmd->layername[0] = '\0';
+ gpmd->materialname[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);
@@ -75,6 +76,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
1,
@@ -82,7 +84,8 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_OFFSET_INVERT_LAYER,
mmd->flag & GP_OFFSET_INVERT_PASS,
- mmd->flag & GP_OFFSET_INVERT_LAYERPASS)) {
+ mmd->flag & GP_OFFSET_INVERT_LAYERPASS,
+ mmd->flag & GP_OFFSET_INVERT_MATERIAL)) {
return;
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
index 92c25f955fb..22610771045 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c
@@ -52,6 +52,7 @@ static void initData(GpencilModifierData *md)
gpmd->pass_index = 0;
gpmd->factor = 1.0f;
gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
gpmd->flag |= GP_OPACITY_CREATE_COLORS;
gpmd->modify_color = GP_MODIFY_COLOR_BOTH;
@@ -75,6 +76,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
1,
@@ -82,7 +84,8 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_OPACITY_INVERT_LAYER,
mmd->flag & GP_OPACITY_INVERT_PASS,
- mmd->flag & GP_OPACITY_INVERT_LAYERPASS)) {
+ mmd->flag & GP_OPACITY_INVERT_LAYERPASS,
+ mmd->flag & GP_OPACITY_INVERT_MATERIAL)) {
return;
}
@@ -109,22 +112,7 @@ static void deformStroke(GpencilModifierData *md,
if (mmd->factor > 1.0f) {
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
- MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
-
- /* verify vertex group */
- float weight = get_modifier_point_weight(
- dvert, (mmd->flag & GP_OPACITY_INVERT_VGROUP) != 0, def_nr);
- if (weight < 0.0f) {
- continue;
- }
- if (def_nr < 0) {
- pt->strength += mmd->factor - 1.0f;
- }
- else {
- CLAMP(weight, 0.0f, 1.0f);
- weight = 1.0f - weight;
- pt->strength += (mmd->factor * weight) - 1.0f;
- }
+ pt->strength += mmd->factor - 1.0f;
CLAMP(pt->strength, 0.0f, 1.0f);
}
}
@@ -145,14 +133,12 @@ static void deformStroke(GpencilModifierData *md,
pt->strength += mmd->factor - 1.0f;
}
else {
- CLAMP(weight, 0.0f, 1.0f);
- weight = 1.0f - weight;
/* High factor values, change weight too. */
if ((mmd->factor > 1.0f) && (weight < 1.0f)) {
weight += mmd->factor - 1.0f;
CLAMP(weight, 0.0f, 1.0f);
}
- pt->strength += (mmd->factor * weight) - 1.0f;
+ pt->strength += (mmd->factor - 1) * weight;
}
CLAMP(pt->strength, 0.0f, 1.0f);
}
@@ -169,7 +155,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
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);
+ Material *mat = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
if (mat == NULL) {
continue;
}
@@ -184,8 +170,10 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
deformStroke(md, depsgraph, ob, gpl, gpf, gps);
- gpencil_apply_modifier_material(
- bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_OPACITY_CREATE_COLORS));
+ if (mmd->opacity_mode == GP_OPACITY_MODE_MATERIAL) {
+ gpencil_apply_modifier_material(
+ bmain, ob, mat, gh_color, gps, (bool)(mmd->flag & GP_OPACITY_CREATE_COLORS));
+ }
}
}
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
index 2168e7f07ec..25a56c4385c 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c
@@ -48,6 +48,7 @@ static void initData(GpencilModifierData *md)
gpmd->length = 0.1f;
gpmd->distance = 0.1f;
gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
@@ -66,6 +67,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
mmd->mode == GP_SIMPLIFY_SAMPLE ? 3 : 4,
@@ -73,7 +75,8 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_SIMPLIFY_INVERT_LAYER,
mmd->flag & GP_SIMPLIFY_INVERT_PASS,
- mmd->flag & GP_SIMPLIFY_INVERT_LAYERPASS)) {
+ mmd->flag & GP_SIMPLIFY_INVERT_LAYERPASS,
+ mmd->flag & GP_SIMPLIFY_INVERT_MATERIAL)) {
return;
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
index 7c639bd8af0..5ec7fe4ff18 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c
@@ -46,6 +46,7 @@ static void initData(GpencilModifierData *md)
gpmd->flag |= GP_SMOOTH_MOD_LOCATION;
gpmd->factor = 0.5f;
gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
gpmd->step = 1;
}
@@ -68,6 +69,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
3,
@@ -75,7 +77,8 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_SMOOTH_INVERT_LAYER,
mmd->flag & GP_SMOOTH_INVERT_PASS,
- mmd->flag & GP_SMOOTH_INVERT_LAYERPASS)) {
+ mmd->flag & GP_SMOOTH_INVERT_LAYERPASS,
+ mmd->flag & GP_SMOOTH_INVERT_MATERIAL)) {
return;
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
index c8962cd58c9..741555722b5 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c
@@ -47,6 +47,7 @@ static void initData(GpencilModifierData *md)
gpmd->pass_index = 0;
gpmd->level = 1;
gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
}
static void copyData(const GpencilModifierData *md, GpencilModifierData *target)
@@ -66,6 +67,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
3,
@@ -73,7 +75,8 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_SUBDIV_INVERT_LAYER,
mmd->flag & GP_SUBDIV_INVERT_PASS,
- mmd->flag & GP_SUBDIV_INVERT_LAYERPASS)) {
+ mmd->flag & GP_SUBDIV_INVERT_LAYERPASS,
+ mmd->flag & GP_SUBDIV_INVERT_MATERIAL)) {
return;
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
index 53abfdf177c..cc38df141d1 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c
@@ -47,6 +47,7 @@ static void initData(GpencilModifierData *md)
gpmd->pass_index = 0;
gpmd->thickness = 2;
gpmd->layername[0] = '\0';
+ gpmd->materialname[0] = '\0';
gpmd->vgname[0] = '\0';
gpmd->curve_thickness = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
if (gpmd->curve_thickness) {
@@ -91,6 +92,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
1,
@@ -98,20 +100,46 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_THICK_INVERT_LAYER,
mmd->flag & GP_THICK_INVERT_PASS,
- mmd->flag & GP_THICK_INVERT_LAYERPASS)) {
+ mmd->flag & GP_THICK_INVERT_LAYERPASS,
+ mmd->flag & GP_THICK_INVERT_MATERIAL)) {
return;
}
- /* if normalize, set stroke thickness */
+ /* Check to see if we normalize the whole stroke or only certain points along it. */
+ bool gps_has_affected_points = false;
+ bool gps_has_unaffected_points = false;
+
if (mmd->flag & GP_THICK_NORMALIZE) {
+ for (int i = 0; i < gps->totpoints; i++) {
+ MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
+ const float weight = get_modifier_point_weight(
+ dvert, (mmd->flag & GP_THICK_INVERT_VGROUP) != 0, def_nr);
+ if (weight < 0.0f) {
+ gps_has_unaffected_points = true;
+ }
+ else {
+ gps_has_affected_points = true;
+ }
+
+ /* If both checks are true, we have what we need so we can stop looking. */
+ if (gps_has_affected_points && gps_has_unaffected_points) {
+ break;
+ }
+ }
+ }
+
+ /* If we are normalizing and all points of the stroke are affected, it's safe to reset thickness
+ */
+ if (mmd->flag & GP_THICK_NORMALIZE && gps_has_affected_points && !gps_has_unaffected_points) {
gps->thickness = mmd->thickness;
}
+ /* Without this check, modifier alters the thickness of strokes which have no points in scope */
for (int i = 0; i < gps->totpoints; i++) {
bGPDspoint *pt = &gps->points[i];
MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL;
float curvef = 1.0f;
- /* verify vertex group */
+ /* Verify point is part of vertex group. */
const float weight = get_modifier_point_weight(
dvert, (mmd->flag & GP_THICK_INVERT_VGROUP) != 0, def_nr);
if (weight < 0.0f) {
@@ -127,11 +155,21 @@ static void deformStroke(GpencilModifierData *md,
float new_pressure = weight * curvef;
if (mmd->flag & GP_THICK_NORMALIZE) {
- pt->pressure = 1.0f * new_pressure;
+ if (gps_has_unaffected_points) {
+ /* Clamp value for very weird situations when stroke thickness can be zero. */
+ CLAMP_MIN(gps->thickness, 1);
+ /* Calculate pressure value to match the width of strokes with reset thickness and 1.0
+ * pressure. */
+ pt->pressure = (float)mmd->thickness / (float)gps->thickness;
+ }
+ else {
+ /* Reset point pressure values so only stroke thickness counts. */
+ pt->pressure = 1.0f;
+ }
}
else {
if ((mmd->flag & GP_THICK_CUSTOM_CURVE) && (mmd->curve_thickness)) {
- /* normalize value to evaluate curve */
+ /* Normalize value to evaluate curve. */
float value = (float)i / (gps->totpoints - 1);
curvef = BKE_curvemapping_evaluateF(mmd->curve_thickness, 0, value);
}
diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
index d70d975c3a7..f6ddcf89bcf 100644
--- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
+++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c
@@ -50,6 +50,7 @@ static void initData(GpencilModifierData *md)
gpmd->pass_index = 0;
gpmd->factor = 0.5f;
gpmd->layername[0] = '\0';
+ gpmd->materialname[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;
@@ -72,6 +73,7 @@ static void deformStroke(GpencilModifierData *md,
if (!is_stroke_affected_by_modifier(ob,
mmd->layername,
+ mmd->materialname,
mmd->pass_index,
mmd->layer_pass,
1,
@@ -79,7 +81,8 @@ static void deformStroke(GpencilModifierData *md,
gps,
mmd->flag & GP_TINT_INVERT_LAYER,
mmd->flag & GP_TINT_INVERT_PASS,
- mmd->flag & GP_TINT_INVERT_LAYERPASS)) {
+ mmd->flag & GP_TINT_INVERT_LAYERPASS,
+ mmd->flag & GP_TINT_INVERT_MATERIAL)) {
return;
}
@@ -122,7 +125,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData
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);
+ Material *mat = BKE_material_gpencil_get(ob, gps->mat_nr + 1);
if (mat == NULL) {
continue;
}
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index fb7d3c1ace8..f11dcc9bcf0 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -116,6 +116,7 @@ set(SRC
intern/gpu_batch_private.h
intern/gpu_codegen.h
intern/gpu_context_private.h
+ intern/gpu_material_library.h
intern/gpu_matrix_private.h
intern/gpu_primitive_private.h
intern/gpu_private.h
@@ -231,7 +232,94 @@ data_to_c_simple(shaders/gpu_shader_keyframe_diamond_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_keyframe_diamond_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_material.glsl SRC)
+
+data_to_c_simple(shaders/material/gpu_shader_material_add_shader.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_ambient_occlusion.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_anisotropic.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_attribute.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_background.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_bevel.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_blackbody.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_bright_contrast.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_bump.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_camera.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_cell_noise.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_clamp.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_color_ramp.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_color_util.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_combine_hsv.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_combine_rgb.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_combine_xyz.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_diffuse.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_displacement.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_eevee_specular.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_emission.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_fractal_noise.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_fresnel.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_gamma.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_geometry.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_glass.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_glossy.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_hair_info.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_hash.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_holdout.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_hue_sat_val.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_invert.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_layer_weight.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_light_falloff.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_light_path.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_mapping.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_map_range.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_math.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_math_util.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_mix_rgb.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_mix_shader.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_noise.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_normal.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_normal_map.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_object_info.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_output_material.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_output_world.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_particle_info.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_principled.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_refraction.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_rgb_curves.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_rgb_to_bw.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_separate_hsv.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_separate_rgb.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_separate_xyz.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_set.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_shader_to_rgba.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_squeeze.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_subsurface_scattering.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tangent.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_brick.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_checker.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_environment.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_gradient.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_image.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_magic.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_musgrave.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_noise.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_sky.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_texture_coordinates.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_voronoi.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_wave.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_tex_white_noise.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_toon.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_translucent.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_transparent.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_uv_map.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_vector_curves.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_vector_displacement.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_vector_math.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_velvet.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_volume_absorption.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_volume_info.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_volume_principled.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_volume_scatter.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_wireframe.glsl SRC)
+data_to_c_simple(shaders/material/gpu_shader_material_world_normals.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)
diff --git a/source/blender/gpu/GPU_batch_presets.h b/source/blender/gpu/GPU_batch_presets.h
index 4b95783e6fa..55d2e461b30 100644
--- a/source/blender/gpu/GPU_batch_presets.h
+++ b/source/blender/gpu/GPU_batch_presets.h
@@ -27,9 +27,6 @@
#ifndef __GPU_BATCH_PRESETS_H__
#define __GPU_BATCH_PRESETS_H__
-struct GPUVertFormat;
-struct rctf;
-
#include "BLI_compiler_attrs.h"
#include "BLI_sys_types.h"
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 507baa9531e..7814c723fec 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -28,17 +28,11 @@
extern "C" {
#endif
-struct DupliObject;
struct ImBuf;
struct Image;
struct ImageUser;
struct Main;
-struct Object;
-struct RegionView3D;
-struct Scene;
struct SmokeModifierData;
-struct View3D;
-struct ViewLayer;
#include "DNA_object_enums.h"
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index dd5292d9c58..4dc0019978a 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -45,10 +45,7 @@ struct ImageUser;
struct ListBase;
struct Main;
struct Material;
-struct Object;
-struct PreviewImage;
struct Scene;
-struct World;
struct bNode;
struct bNodeTree;
@@ -92,7 +89,7 @@ typedef enum eGPUBuiltin {
GPU_INVERSE_OBJECT_MATRIX = (1 << 3),
GPU_VIEW_POSITION = (1 << 4),
GPU_VIEW_NORMAL = (1 << 5),
- GPU_OBCOLOR = (1 << 6),
+ GPU_OBJECT_COLOR = (1 << 6),
GPU_AUTO_BUMPSCALE = (1 << 7),
GPU_CAMERA_TEXCO_FACTORS = (1 << 8),
GPU_PARTICLE_SCALAR_PROPS = (1 << 9),
diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h
index d3a9a18b392..ec97e1b085e 100644
--- a/source/blender/gpu/GPU_shader_interface.h
+++ b/source/blender/gpu/GPU_shader_interface.h
@@ -48,9 +48,10 @@ typedef enum {
GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */
GPU_UNIFORM_CLIPPLANES, /* vec4 WorldClipPlanes[] */
- GPU_UNIFORM_COLOR, /* vec4 color */
- GPU_UNIFORM_CALLID, /* int callId */
- GPU_UNIFORM_OBJECT_INFO, /* vec3 objectInfo */
+ GPU_UNIFORM_COLOR, /* vec4 color */
+ GPU_UNIFORM_CALLID, /* int callId */
+ GPU_UNIFORM_OBJECT_INFO, /* vec3 objectInfo */
+ GPU_UNIFORM_OBJECT_COLOR, /* vec4 objectColor */
GPU_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 2b61d99e852..a8e8ca72023 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -36,7 +36,6 @@ struct ImageUser;
struct MovieClip;
struct MovieClipUser;
struct PreviewImage;
-struct rcti;
struct GPUFrameBuffer;
typedef struct GPUTexture GPUTexture;
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 0e15fdd000b..d655a43561e 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -51,15 +51,11 @@
#include "BLI_sys_types.h" /* for intptr_t support */
#include "gpu_codegen.h"
+#include "gpu_material_library.h"
#include <string.h>
#include <stdarg.h>
-extern char datatoc_gpu_shader_material_glsl[];
-extern char datatoc_gpu_shader_geometry_glsl[];
-
-static char *glsl_material_library = NULL;
-
/* -------------------- GPUPass Cache ------------------ */
/**
* Internal shader cache: This prevent the shader recompilation / stall when
@@ -147,6 +143,7 @@ typedef struct GPUFunction {
eGPUType paramtype[MAX_PARAMETER];
GPUFunctionQual paramqual[MAX_PARAMETER];
int totparam;
+ GPUMaterialLibrary *library;
} GPUFunction;
/* Indices match the eGPUType enum */
@@ -230,15 +227,17 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
return str;
}
-static void gpu_parse_functions_string(GHash *hash, char *code)
+static void gpu_parse_material_library(GHash *hash, GPUMaterialLibrary *library)
{
GPUFunction *function;
eGPUType type;
GPUFunctionQual qual;
int i;
+ char *code = library->code;
while ((code = strstr(code, "void "))) {
function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
+ function->library = library;
code = gpu_str_skip_token(code, NULL, 0);
code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME);
@@ -367,11 +366,6 @@ static char *gpu_generate_function_prototyps(GHash *hash)
static GPUFunction *gpu_lookup_function(const char *name)
{
- if (!FUNCTION_HASH) {
- FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
- gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
- }
-
return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
}
@@ -395,11 +389,6 @@ void gpu_codegen_exit(void)
GPU_shader_free_builtin_shaders();
- if (glsl_material_library) {
- MEM_freeN(glsl_material_library);
- glsl_material_library = NULL;
- }
-
#if 0
if (FUNCTION_PROTOTYPES) {
MEM_freeN(FUNCTION_PROTOTYPES);
@@ -425,7 +414,7 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t
}
else if (to == GPU_FLOAT) {
if (from == GPU_VEC4) {
- BLI_dynstr_appendf(ds, "convert_rgba_to_float(%s)", name);
+ BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.2126, 0.7152, 0.0722))", name);
}
else if (from == GPU_VEC3) {
BLI_dynstr_appendf(ds, "(%s.r + %s.g + %s.b) / 3.0", name, name, name);
@@ -542,8 +531,8 @@ const char *GPU_builtin_name(eGPUBuiltin builtin)
else if (builtin == GPU_VIEW_NORMAL) {
return "varnormal";
}
- else if (builtin == GPU_OBCOLOR) {
- return "unfobcolor";
+ else if (builtin == GPU_OBJECT_COLOR) {
+ return "unfobjectcolor";
}
else if (builtin == GPU_AUTO_BUMPSCALE) {
return "unfobautobumpscale";
@@ -1381,20 +1370,15 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
void GPU_code_generate_glsl_lib(void)
{
- DynStr *ds;
-
- /* only initialize the library once */
- if (glsl_material_library) {
+ /* Only parse GLSL shader files once. */
+ if (FUNCTION_HASH) {
return;
}
- ds = BLI_dynstr_new();
-
- BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl);
-
- glsl_material_library = BLI_dynstr_get_cstring(ds);
-
- BLI_dynstr_free(ds);
+ FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
+ for (int i = 0; gpu_material_libraries[i]; i++) {
+ gpu_parse_material_library(FUNCTION_HASH, gpu_material_libraries[i]);
+ }
}
/* GPU pass binding/unbinding */
@@ -1796,6 +1780,22 @@ GPUNodeLink *GPU_builtin(eGPUBuiltin builtin)
return link;
}
+static void gpu_material_use_library_with_dependencies(GSet *used_libraries,
+ GPUMaterialLibrary *library)
+{
+ if (BLI_gset_add(used_libraries, library->code)) {
+ for (int i = 0; library->dependencies[i]; i++) {
+ gpu_material_use_library_with_dependencies(used_libraries, library->dependencies[i]);
+ }
+ }
+}
+
+static void gpu_material_use_library(GPUMaterial *material, GPUMaterialLibrary *library)
+{
+ GSet *used_libraries = gpu_material_used_libraries(material);
+ gpu_material_use_library_with_dependencies(used_libraries, library);
+}
+
bool GPU_link(GPUMaterial *mat, const char *name, ...)
{
GPUNode *node;
@@ -1810,6 +1810,8 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
return false;
}
+ gpu_material_use_library(mat, function->library);
+
node = GPU_node_begin(name);
va_start(params, name);
@@ -1849,6 +1851,8 @@ bool GPU_stack_link(GPUMaterial *material,
return false;
}
+ gpu_material_use_library(material, function->library);
+
node = GPU_node_begin(name);
totin = 0;
totout = 0;
@@ -1962,6 +1966,34 @@ static bool gpu_pass_is_valid(GPUPass *pass)
return (pass->compiled == false || pass->shader != NULL);
}
+static char *code_generate_material_library(GPUMaterial *material, const char *frag_lib)
+{
+ DynStr *ds = BLI_dynstr_new();
+
+ if (frag_lib) {
+ BLI_dynstr_append(ds, frag_lib);
+ }
+
+ GSet *used_libraries = gpu_material_used_libraries(material);
+
+ /* Always include those because they may be needed by the execution function. */
+ gpu_material_use_library_with_dependencies(used_libraries,
+ &gpu_shader_material_world_normals_library);
+
+ /* Add library code in order, for dependencies. */
+ for (int i = 0; gpu_material_libraries[i]; i++) {
+ GPUMaterialLibrary *library = gpu_material_libraries[i];
+ if (BLI_gset_haskey(used_libraries, library->code)) {
+ BLI_dynstr_append(ds, library->code);
+ }
+ }
+
+ char *result = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return result;
+}
+
GPUPass *GPU_generate_pass(GPUMaterial *material,
GPUNodeLink *frag_outlink,
struct GPUVertAttrLayers *attrs,
@@ -2000,7 +2032,7 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
/* Either the shader is not compiled or there is a hash collision...
* continue generating the shader strings. */
- char *tmp = BLI_strdupcat(frag_lib, glsl_material_library);
+ char *tmp = code_generate_material_library(material, frag_lib);
geometrycode = code_generate_geometry(nodes, geom_code, defines);
vertexcode = code_generate_vertex(nodes, vert_code, (geometrycode != NULL));
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index ae34e21b9cd..4e09f16ebf8 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -33,8 +33,8 @@ struct GPUNode;
struct GPUOutput;
struct GPUShader;
struct GPUVertAttrLayers;
+struct GSet;
struct ListBase;
-struct PreviewImage;
/* Pass Generation
* - Takes a list of nodes and a desired output, and makes a pass. This
@@ -208,4 +208,6 @@ struct GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat,
float *pixels,
float *row);
+struct GSet *gpu_material_used_libraries(struct GPUMaterial *material);
+
#endif
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index be3655648f5..859b1e4a10d 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -348,7 +348,7 @@ static void gpu_texture_update_scaled(
}
/* Scale pixels. */
- ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, w, h);
+ ImBuf *ibuf = IMB_allocFromBuffer((uint *)rect, rect_float, w, h, 4);
IMB_scaleImBuf(ibuf, sub_w, sub_h);
if (ibuf->rect_float) {
@@ -648,13 +648,13 @@ void GPU_create_gl_tex(uint *bind,
recth = smaller_power_of_2_limit(recth);
if (frect) {
- ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
+ ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy, 4);
IMB_scaleImBuf(ibuf, rectw, recth);
frect = ibuf->rect_float;
}
else {
- ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
+ ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy, 4);
IMB_scaleImBuf(ibuf, rectw, recth);
rect = ibuf->rect;
diff --git a/source/blender/gpu/intern/gpu_element.c b/source/blender/gpu/intern/gpu_element.c
index 6c9331b4903..3f3f246d6d9 100644
--- a/source/blender/gpu/intern/gpu_element.c
+++ b/source/blender/gpu/intern/gpu_element.c
@@ -267,9 +267,9 @@ static uint index_range(const uint values[], uint value_len, uint *min_out, uint
*max_out = 0;
return 0;
}
- uint min_value = values[0];
- uint max_value = values[0];
- for (uint i = 1; i < value_len; ++i) {
+ uint min_value = RESTART_INDEX;
+ uint max_value = 0;
+ for (uint i = 0; i < value_len; ++i) {
const uint value = values[i];
if (value == RESTART_INDEX) {
continue;
@@ -281,9 +281,16 @@ static uint index_range(const uint values[], uint value_len, uint *min_out, uint
max_value = value;
}
}
- *min_out = min_value;
- *max_out = max_value;
- return max_value - min_value;
+ if (min_value == RESTART_INDEX) {
+ *min_out = 0;
+ *max_out = 0;
+ return 0;
+ }
+ else {
+ *min_out = min_value;
+ *max_out = max_value;
+ return max_value - min_value;
+ }
}
static void squeeze_indices_short(GPUIndexBufBuilder *builder,
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 99dbff05453..5839b34cd19 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -309,6 +309,7 @@ void gpu_extensions_init(void)
}
else if ((strstr(renderer, "Mesa DRI R")) ||
(strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) ||
+ (strstr(renderer, "AMD") && strstr(vendor, "X.Org")) ||
(strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) ||
(strstr(renderer, "Gallium ") && strstr(renderer, " on AMD "))) {
GG.device = GPU_DEVICE_ATI;
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 20b91c0c95d..05d991105c0 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -37,6 +37,7 @@
#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_string_utils.h"
+#include "BLI_ghash.h"
#include "BKE_main.h"
#include "BKE_node.h"
@@ -102,6 +103,8 @@ struct GPUMaterial {
GPUTexture *coba_tex; /* 1D Texture array containing all color bands. */
GPUColorBandBuilder *coba_builder;
+ GSet *used_libraries;
+
#ifndef NDEBUG
char name[64];
#endif
@@ -183,6 +186,8 @@ static void gpu_material_free_single(GPUMaterial *material)
if (material->coba_tex != NULL) {
GPU_texture_free(material->coba_tex);
}
+
+ BLI_gset_free(material->used_libraries, NULL);
}
void GPU_material_free(ListBase *gpumaterial)
@@ -582,6 +587,11 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
BLI_addtail(&material->nodes, node);
}
+GSet *gpu_material_used_libraries(GPUMaterial *material)
+{
+ return material->used_libraries;
+}
+
/* Return true if the material compilation has not yet begin or begin. */
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
{
@@ -659,6 +669,9 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
UNUSED_VARS(name);
#endif
+ mat->used_libraries = BLI_gset_new(
+ BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "GPUMaterial.used_libraries");
+
/* localize tree to create links for reroute and mute */
bNodeTree *localtree = ntreeLocalize(ntree);
ntreeGPUMaterialNodes(localtree, mat, &has_surface_output, &has_volume_output);
diff --git a/source/blender/gpu/intern/gpu_material_library.h b/source/blender/gpu/intern/gpu_material_library.h
new file mode 100644
index 00000000000..99a71094753
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_material_library.h
@@ -0,0 +1,657 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup gpu
+ *
+ * List of all gpu_shader_material_*.glsl files used by GLSL materials. These
+ * will be parsed to make all functions in them available to use for GPU_link().
+ *
+ * If a file uses functions from another file, it must be added to the list of
+ * dependencies, and be placed after that file in the list. */
+
+#ifndef __GPU_MATERIAL_LIBRARY_H__
+#define __GPU_MATERIAL_LIBRARY_H__
+
+typedef struct GPUMaterialLibrary {
+ char *code;
+ struct GPUMaterialLibrary *dependencies[8];
+} GPUMaterialLibrary;
+
+extern char datatoc_gpu_shader_material_add_shader_glsl[];
+extern char datatoc_gpu_shader_material_ambient_occlusion_glsl[];
+extern char datatoc_gpu_shader_material_anisotropic_glsl[];
+extern char datatoc_gpu_shader_material_attribute_glsl[];
+extern char datatoc_gpu_shader_material_background_glsl[];
+extern char datatoc_gpu_shader_material_bevel_glsl[];
+extern char datatoc_gpu_shader_material_blackbody_glsl[];
+extern char datatoc_gpu_shader_material_bright_contrast_glsl[];
+extern char datatoc_gpu_shader_material_bump_glsl[];
+extern char datatoc_gpu_shader_material_camera_glsl[];
+extern char datatoc_gpu_shader_material_cell_noise_glsl[];
+extern char datatoc_gpu_shader_material_clamp_glsl[];
+extern char datatoc_gpu_shader_material_color_ramp_glsl[];
+extern char datatoc_gpu_shader_material_color_util_glsl[];
+extern char datatoc_gpu_shader_material_combine_hsv_glsl[];
+extern char datatoc_gpu_shader_material_combine_rgb_glsl[];
+extern char datatoc_gpu_shader_material_combine_xyz_glsl[];
+extern char datatoc_gpu_shader_material_diffuse_glsl[];
+extern char datatoc_gpu_shader_material_displacement_glsl[];
+extern char datatoc_gpu_shader_material_eevee_specular_glsl[];
+extern char datatoc_gpu_shader_material_emission_glsl[];
+extern char datatoc_gpu_shader_material_fractal_noise_glsl[];
+extern char datatoc_gpu_shader_material_fresnel_glsl[];
+extern char datatoc_gpu_shader_material_gamma_glsl[];
+extern char datatoc_gpu_shader_material_geometry_glsl[];
+extern char datatoc_gpu_shader_material_glass_glsl[];
+extern char datatoc_gpu_shader_material_glossy_glsl[];
+extern char datatoc_gpu_shader_material_hair_info_glsl[];
+extern char datatoc_gpu_shader_material_hash_glsl[];
+extern char datatoc_gpu_shader_material_holdout_glsl[];
+extern char datatoc_gpu_shader_material_hue_sat_val_glsl[];
+extern char datatoc_gpu_shader_material_invert_glsl[];
+extern char datatoc_gpu_shader_material_layer_weight_glsl[];
+extern char datatoc_gpu_shader_material_light_falloff_glsl[];
+extern char datatoc_gpu_shader_material_light_path_glsl[];
+extern char datatoc_gpu_shader_material_mapping_glsl[];
+extern char datatoc_gpu_shader_material_map_range_glsl[];
+extern char datatoc_gpu_shader_material_math_glsl[];
+extern char datatoc_gpu_shader_material_math_util_glsl[];
+extern char datatoc_gpu_shader_material_mix_rgb_glsl[];
+extern char datatoc_gpu_shader_material_mix_shader_glsl[];
+extern char datatoc_gpu_shader_material_noise_glsl[];
+extern char datatoc_gpu_shader_material_normal_glsl[];
+extern char datatoc_gpu_shader_material_normal_map_glsl[];
+extern char datatoc_gpu_shader_material_object_info_glsl[];
+extern char datatoc_gpu_shader_material_output_material_glsl[];
+extern char datatoc_gpu_shader_material_output_world_glsl[];
+extern char datatoc_gpu_shader_material_particle_info_glsl[];
+extern char datatoc_gpu_shader_material_principled_glsl[];
+extern char datatoc_gpu_shader_material_refraction_glsl[];
+extern char datatoc_gpu_shader_material_rgb_curves_glsl[];
+extern char datatoc_gpu_shader_material_rgb_to_bw_glsl[];
+extern char datatoc_gpu_shader_material_separate_hsv_glsl[];
+extern char datatoc_gpu_shader_material_separate_rgb_glsl[];
+extern char datatoc_gpu_shader_material_separate_xyz_glsl[];
+extern char datatoc_gpu_shader_material_set_glsl[];
+extern char datatoc_gpu_shader_material_shader_to_rgba_glsl[];
+extern char datatoc_gpu_shader_material_squeeze_glsl[];
+extern char datatoc_gpu_shader_material_subsurface_scattering_glsl[];
+extern char datatoc_gpu_shader_material_tangent_glsl[];
+extern char datatoc_gpu_shader_material_tex_brick_glsl[];
+extern char datatoc_gpu_shader_material_tex_checker_glsl[];
+extern char datatoc_gpu_shader_material_tex_environment_glsl[];
+extern char datatoc_gpu_shader_material_tex_gradient_glsl[];
+extern char datatoc_gpu_shader_material_tex_image_glsl[];
+extern char datatoc_gpu_shader_material_tex_magic_glsl[];
+extern char datatoc_gpu_shader_material_tex_musgrave_glsl[];
+extern char datatoc_gpu_shader_material_tex_noise_glsl[];
+extern char datatoc_gpu_shader_material_tex_sky_glsl[];
+extern char datatoc_gpu_shader_material_texture_coordinates_glsl[];
+extern char datatoc_gpu_shader_material_tex_voronoi_glsl[];
+extern char datatoc_gpu_shader_material_tex_wave_glsl[];
+extern char datatoc_gpu_shader_material_tex_white_noise_glsl[];
+extern char datatoc_gpu_shader_material_toon_glsl[];
+extern char datatoc_gpu_shader_material_translucent_glsl[];
+extern char datatoc_gpu_shader_material_transparent_glsl[];
+extern char datatoc_gpu_shader_material_uv_map_glsl[];
+extern char datatoc_gpu_shader_material_vector_curves_glsl[];
+extern char datatoc_gpu_shader_material_vector_displacement_glsl[];
+extern char datatoc_gpu_shader_material_vector_math_glsl[];
+extern char datatoc_gpu_shader_material_velvet_glsl[];
+extern char datatoc_gpu_shader_material_volume_absorption_glsl[];
+extern char datatoc_gpu_shader_material_volume_info_glsl[];
+extern char datatoc_gpu_shader_material_volume_principled_glsl[];
+extern char datatoc_gpu_shader_material_volume_scatter_glsl[];
+extern char datatoc_gpu_shader_material_wireframe_glsl[];
+extern char datatoc_gpu_shader_material_world_normals_glsl[];
+
+static GPUMaterialLibrary gpu_shader_material_math_util_library = {
+ .code = datatoc_gpu_shader_material_math_util_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_color_util_library = {
+ .code = datatoc_gpu_shader_material_color_util_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_hash_library = {
+ .code = datatoc_gpu_shader_material_hash_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_noise_library = {
+ .code = datatoc_gpu_shader_material_noise_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library,
+ &gpu_shader_material_hash_library,
+ NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_fractal_noise_library = {
+ .code = datatoc_gpu_shader_material_fractal_noise_glsl,
+ .dependencies = {&gpu_shader_material_noise_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_cell_noise_library = {
+ .code = datatoc_gpu_shader_material_cell_noise_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library,
+ &gpu_shader_material_hash_library,
+ NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_add_shader_library = {
+ .code = datatoc_gpu_shader_material_add_shader_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_ambient_occlusion_library = {
+ .code = datatoc_gpu_shader_material_ambient_occlusion_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_glossy_library = {
+ .code = datatoc_gpu_shader_material_glossy_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_anisotropic_library = {
+ .code = datatoc_gpu_shader_material_anisotropic_glsl,
+ .dependencies = {&gpu_shader_material_glossy_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_attribute_library = {
+ .code = datatoc_gpu_shader_material_attribute_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_background_library = {
+ .code = datatoc_gpu_shader_material_background_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_bevel_library = {
+ .code = datatoc_gpu_shader_material_bevel_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_blackbody_library = {
+ .code = datatoc_gpu_shader_material_blackbody_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_bright_contrast_library = {
+ .code = datatoc_gpu_shader_material_bright_contrast_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_bump_library = {
+ .code = datatoc_gpu_shader_material_bump_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_camera_library = {
+ .code = datatoc_gpu_shader_material_camera_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_clamp_library = {
+ .code = datatoc_gpu_shader_material_clamp_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_color_ramp_library = {
+ .code = datatoc_gpu_shader_material_color_ramp_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_combine_hsv_library = {
+ .code = datatoc_gpu_shader_material_combine_hsv_glsl,
+ .dependencies = {&gpu_shader_material_color_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_combine_rgb_library = {
+ .code = datatoc_gpu_shader_material_combine_rgb_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_combine_xyz_library = {
+ .code = datatoc_gpu_shader_material_combine_xyz_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_diffuse_library = {
+ .code = datatoc_gpu_shader_material_diffuse_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_displacement_library = {
+ .code = datatoc_gpu_shader_material_displacement_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_eevee_specular_library = {
+ .code = datatoc_gpu_shader_material_eevee_specular_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_emission_library = {
+ .code = datatoc_gpu_shader_material_emission_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_fresnel_library = {
+ .code = datatoc_gpu_shader_material_fresnel_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_gamma_library = {
+ .code = datatoc_gpu_shader_material_gamma_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tangent_library = {
+ .code = datatoc_gpu_shader_material_tangent_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_geometry_library = {
+ .code = datatoc_gpu_shader_material_geometry_glsl,
+ .dependencies = {&gpu_shader_material_tangent_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_glass_library = {
+ .code = datatoc_gpu_shader_material_glass_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_hair_info_library = {
+ .code = datatoc_gpu_shader_material_hair_info_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_holdout_library = {
+ .code = datatoc_gpu_shader_material_holdout_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_hue_sat_val_library = {
+ .code = datatoc_gpu_shader_material_hue_sat_val_glsl,
+ .dependencies = {&gpu_shader_material_color_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_invert_library = {
+ .code = datatoc_gpu_shader_material_invert_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_layer_weight_library = {
+ .code = datatoc_gpu_shader_material_layer_weight_glsl,
+ .dependencies = {&gpu_shader_material_fresnel_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_light_falloff_library = {
+ .code = datatoc_gpu_shader_material_light_falloff_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_light_path_library = {
+ .code = datatoc_gpu_shader_material_light_path_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_mapping_library = {
+ .code = datatoc_gpu_shader_material_mapping_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_map_range_library = {
+ .code = datatoc_gpu_shader_material_map_range_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_math_library = {
+ .code = datatoc_gpu_shader_material_math_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_mix_rgb_library = {
+ .code = datatoc_gpu_shader_material_mix_rgb_glsl,
+ .dependencies = {&gpu_shader_material_color_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_mix_shader_library = {
+ .code = datatoc_gpu_shader_material_mix_shader_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_normal_library = {
+ .code = datatoc_gpu_shader_material_normal_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_normal_map_library = {
+ .code = datatoc_gpu_shader_material_normal_map_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_object_info_library = {
+ .code = datatoc_gpu_shader_material_object_info_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_output_material_library = {
+ .code = datatoc_gpu_shader_material_output_material_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_output_world_library = {
+ .code = datatoc_gpu_shader_material_output_world_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_particle_info_library = {
+ .code = datatoc_gpu_shader_material_particle_info_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_principled_library = {
+ .code = datatoc_gpu_shader_material_principled_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_refraction_library = {
+ .code = datatoc_gpu_shader_material_refraction_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_rgb_curves_library = {
+ .code = datatoc_gpu_shader_material_rgb_curves_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_rgb_to_bw_library = {
+ .code = datatoc_gpu_shader_material_rgb_to_bw_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_separate_hsv_library = {
+ .code = datatoc_gpu_shader_material_separate_hsv_glsl,
+ .dependencies = {&gpu_shader_material_color_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_separate_rgb_library = {
+ .code = datatoc_gpu_shader_material_separate_rgb_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_separate_xyz_library = {
+ .code = datatoc_gpu_shader_material_separate_xyz_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_set_library = {
+ .code = datatoc_gpu_shader_material_set_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_shader_to_rgba_library = {
+ .code = datatoc_gpu_shader_material_shader_to_rgba_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_squeeze_library = {
+ .code = datatoc_gpu_shader_material_squeeze_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_subsurface_scattering_library = {
+ .code = datatoc_gpu_shader_material_subsurface_scattering_glsl,
+ .dependencies = {&gpu_shader_material_diffuse_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_brick_library = {
+ .code = datatoc_gpu_shader_material_tex_brick_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library,
+ &gpu_shader_material_hash_library,
+ NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_checker_library = {
+ .code = datatoc_gpu_shader_material_tex_checker_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_environment_library = {
+ .code = datatoc_gpu_shader_material_tex_environment_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_gradient_library = {
+ .code = datatoc_gpu_shader_material_tex_gradient_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_image_library = {
+ .code = datatoc_gpu_shader_material_tex_image_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_magic_library = {
+ .code = datatoc_gpu_shader_material_tex_magic_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_musgrave_library = {
+ .code = datatoc_gpu_shader_material_tex_musgrave_glsl,
+ .dependencies = {&gpu_shader_material_noise_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_noise_library = {
+ .code = datatoc_gpu_shader_material_tex_noise_glsl,
+ .dependencies = {&gpu_shader_material_fractal_noise_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_sky_library = {
+ .code = datatoc_gpu_shader_material_tex_sky_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_texture_coordinates_library = {
+ .code = datatoc_gpu_shader_material_texture_coordinates_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_voronoi_library = {
+ .code = datatoc_gpu_shader_material_tex_voronoi_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library,
+ &gpu_shader_material_cell_noise_library,
+ NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_wave_library = {
+ .code = datatoc_gpu_shader_material_tex_wave_glsl,
+ .dependencies = {&gpu_shader_material_fractal_noise_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_tex_white_noise_library = {
+ .code = datatoc_gpu_shader_material_tex_white_noise_glsl,
+ .dependencies = {&gpu_shader_material_hash_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_toon_library = {
+ .code = datatoc_gpu_shader_material_toon_glsl,
+ .dependencies = {&gpu_shader_material_diffuse_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_translucent_library = {
+ .code = datatoc_gpu_shader_material_translucent_glsl,
+ .dependencies = {&gpu_shader_material_diffuse_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_transparent_library = {
+ .code = datatoc_gpu_shader_material_transparent_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_uv_map_library = {
+ .code = datatoc_gpu_shader_material_uv_map_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_vector_curves_library = {
+ .code = datatoc_gpu_shader_material_vector_curves_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_vector_displacement_library = {
+ .code = datatoc_gpu_shader_material_vector_displacement_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_vector_math_library = {
+ .code = datatoc_gpu_shader_material_vector_math_glsl,
+ .dependencies = {&gpu_shader_material_math_util_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_velvet_library = {
+ .code = datatoc_gpu_shader_material_velvet_glsl,
+ .dependencies = {&gpu_shader_material_diffuse_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_volume_absorption_library = {
+ .code = datatoc_gpu_shader_material_volume_absorption_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_volume_info_library = {
+ .code = datatoc_gpu_shader_material_volume_info_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_volume_principled_library = {
+ .code = datatoc_gpu_shader_material_volume_principled_glsl,
+ .dependencies = {&gpu_shader_material_blackbody_library, NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_volume_scatter_library = {
+ .code = datatoc_gpu_shader_material_volume_scatter_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_wireframe_library = {
+ .code = datatoc_gpu_shader_material_wireframe_glsl,
+ .dependencies = {NULL},
+};
+
+static GPUMaterialLibrary gpu_shader_material_world_normals_library = {
+ .code = datatoc_gpu_shader_material_world_normals_glsl,
+ .dependencies = {&gpu_shader_material_texture_coordinates_library, NULL},
+};
+
+static GPUMaterialLibrary *gpu_material_libraries[] = {
+ &gpu_shader_material_math_util_library,
+ &gpu_shader_material_color_util_library,
+ &gpu_shader_material_hash_library,
+ &gpu_shader_material_noise_library,
+ &gpu_shader_material_fractal_noise_library,
+ &gpu_shader_material_cell_noise_library,
+ &gpu_shader_material_add_shader_library,
+ &gpu_shader_material_ambient_occlusion_library,
+ &gpu_shader_material_glossy_library,
+ &gpu_shader_material_anisotropic_library,
+ &gpu_shader_material_attribute_library,
+ &gpu_shader_material_background_library,
+ &gpu_shader_material_bevel_library,
+ &gpu_shader_material_blackbody_library,
+ &gpu_shader_material_bright_contrast_library,
+ &gpu_shader_material_bump_library,
+ &gpu_shader_material_camera_library,
+ &gpu_shader_material_clamp_library,
+ &gpu_shader_material_color_ramp_library,
+ &gpu_shader_material_combine_hsv_library,
+ &gpu_shader_material_combine_rgb_library,
+ &gpu_shader_material_combine_xyz_library,
+ &gpu_shader_material_diffuse_library,
+ &gpu_shader_material_displacement_library,
+ &gpu_shader_material_eevee_specular_library,
+ &gpu_shader_material_emission_library,
+ &gpu_shader_material_fresnel_library,
+ &gpu_shader_material_gamma_library,
+ &gpu_shader_material_tangent_library,
+ &gpu_shader_material_geometry_library,
+ &gpu_shader_material_glass_library,
+ &gpu_shader_material_hair_info_library,
+ &gpu_shader_material_holdout_library,
+ &gpu_shader_material_hue_sat_val_library,
+ &gpu_shader_material_invert_library,
+ &gpu_shader_material_layer_weight_library,
+ &gpu_shader_material_light_falloff_library,
+ &gpu_shader_material_light_path_library,
+ &gpu_shader_material_mapping_library,
+ &gpu_shader_material_map_range_library,
+ &gpu_shader_material_math_library,
+ &gpu_shader_material_mix_rgb_library,
+ &gpu_shader_material_mix_shader_library,
+ &gpu_shader_material_normal_library,
+ &gpu_shader_material_normal_map_library,
+ &gpu_shader_material_object_info_library,
+ &gpu_shader_material_output_material_library,
+ &gpu_shader_material_output_world_library,
+ &gpu_shader_material_particle_info_library,
+ &gpu_shader_material_principled_library,
+ &gpu_shader_material_refraction_library,
+ &gpu_shader_material_rgb_curves_library,
+ &gpu_shader_material_rgb_to_bw_library,
+ &gpu_shader_material_separate_hsv_library,
+ &gpu_shader_material_separate_rgb_library,
+ &gpu_shader_material_separate_xyz_library,
+ &gpu_shader_material_set_library,
+ &gpu_shader_material_shader_to_rgba_library,
+ &gpu_shader_material_squeeze_library,
+ &gpu_shader_material_subsurface_scattering_library,
+ &gpu_shader_material_tex_brick_library,
+ &gpu_shader_material_tex_checker_library,
+ &gpu_shader_material_tex_environment_library,
+ &gpu_shader_material_tex_gradient_library,
+ &gpu_shader_material_tex_image_library,
+ &gpu_shader_material_tex_magic_library,
+ &gpu_shader_material_tex_musgrave_library,
+ &gpu_shader_material_tex_noise_library,
+ &gpu_shader_material_tex_sky_library,
+ &gpu_shader_material_texture_coordinates_library,
+ &gpu_shader_material_tex_voronoi_library,
+ &gpu_shader_material_tex_wave_library,
+ &gpu_shader_material_tex_white_noise_library,
+ &gpu_shader_material_toon_library,
+ &gpu_shader_material_translucent_library,
+ &gpu_shader_material_transparent_library,
+ &gpu_shader_material_uv_map_library,
+ &gpu_shader_material_vector_curves_library,
+ &gpu_shader_material_vector_displacement_library,
+ &gpu_shader_material_vector_math_library,
+ &gpu_shader_material_velvet_library,
+ &gpu_shader_material_volume_absorption_library,
+ &gpu_shader_material_volume_info_library,
+ &gpu_shader_material_volume_principled_library,
+ &gpu_shader_material_volume_scatter_library,
+ &gpu_shader_material_wireframe_library,
+ &gpu_shader_material_world_normals_library,
+ NULL};
+#endif
diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h
index 4b90f8daa8c..43b2da13e28 100644
--- a/source/blender/gpu/intern/gpu_private.h
+++ b/source/blender/gpu/intern/gpu_private.h
@@ -21,9 +21,6 @@
#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_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index e34c6e23024..f205ef31ed2 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -67,6 +67,7 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u)
[GPU_UNIFORM_COLOR] = "color",
[GPU_UNIFORM_CALLID] = "callId",
[GPU_UNIFORM_OBJECT_INFO] = "unfobjectinfo",
+ [GPU_UNIFORM_OBJECT_COLOR] = "unfobjectcolor",
[GPU_UNIFORM_CUSTOM] = NULL,
[GPU_NUM_UNIFORMS] = NULL,
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index dab17fcd72a..955b11036ef 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -1598,7 +1598,7 @@ void GPU_texture_generate_mipmap(GPUTexture *tex)
if (GPU_texture_depth(tex)) {
/* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789).
- * In this case we just create a complete texture with mipmaps manually without downsampling.
+ * In this case we just create a complete texture with mipmaps manually without down-sampling.
* You must initialize the texture levels using other methods like
* GPU_framebuffer_recursive_downsample(). */
int levels = 1 + floor(log2(max_ii(tex->w, tex->h)));
diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c
index 11df86c0b3a..66e5e254734 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.c
+++ b/source/blender/gpu/intern/gpu_vertex_format.c
@@ -253,7 +253,7 @@ void GPU_vertformat_safe_attrib_name(const char *attrib_name,
*(uint *)&data[4] = BLI_ghashutil_strhash_p_murmur(attrib_name + 4);
}
else {
- /* Copy the whole name. Collision is barelly possible
+ /* Copy the whole name. Collision is barely possible
* (hash would have to be equal to the last 4 bytes). */
for (int i = 0; i < 8 && attrib_name[i] != '\0'; i++) {
data[i] = attrib_name[i];
diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
index 8dc92a2b415..2ba89230d80 100644
--- a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl
@@ -1,11 +1,11 @@
uniform mat4 ModelViewProjectionMatrix;
uniform vec2 ViewportSize = vec2(-1, -1);
+uniform float outline_scale = 1.0;
const float line_falloff = 1.0;
const float circle_scale = sqrt(2.0 / 3.1416);
const float square_scale = sqrt(0.5);
-
const float diagonal_scale = sqrt(0.5);
in vec2 pos;
@@ -58,7 +58,7 @@ void main()
float line_width = half_width + line_falloff;
/* Outline thresholds. */
- thresholds.xy = line_thresholds(line_width);
+ thresholds.xy = line_thresholds(line_width * outline_scale);
/* Inner dot thresholds. */
thresholds.zw = line_thresholds(line_width * 1.6);
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
deleted file mode 100644
index f077ae55d8f..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ /dev/null
@@ -1,3615 +0,0 @@
-
-/* Converters */
-
-float convert_rgba_to_float(vec4 color)
-{
- return dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
-}
-
-float exp_blender(float f)
-{
- return pow(2.71828182846, f);
-}
-
-float compatible_pow(float x, float y)
-{
- if (y == 0.0) { /* x^0 -> 1, including 0^0 */
- return 1.0;
- }
-
- /* glsl pow doesn't accept negative x */
- if (x < 0.0) {
- if (mod(-y, 2.0) == 0.0) {
- return pow(-x, y);
- }
- else {
- return -pow(-x, y);
- }
- }
- else if (x == 0.0) {
- return 0.0;
- }
-
- return pow(x, y);
-}
-
-void rgb_to_hsv(vec4 rgb, out vec4 outcol)
-{
- float cmax, cmin, h, s, v, cdelta;
- vec3 c;
-
- cmax = max(rgb[0], max(rgb[1], rgb[2]));
- cmin = min(rgb[0], min(rgb[1], rgb[2]));
- cdelta = cmax - cmin;
-
- v = cmax;
- if (cmax != 0.0) {
- s = cdelta / cmax;
- }
- else {
- s = 0.0;
- h = 0.0;
- }
-
- if (s == 0.0) {
- h = 0.0;
- }
- else {
- c = (vec3(cmax) - rgb.xyz) / cdelta;
-
- if (rgb.x == cmax) {
- h = c[2] - c[1];
- }
- else if (rgb.y == cmax) {
- h = 2.0 + c[0] - c[2];
- }
- else {
- h = 4.0 + c[1] - c[0];
- }
-
- h /= 6.0;
-
- if (h < 0.0) {
- h += 1.0;
- }
- }
-
- outcol = vec4(h, s, v, rgb.w);
-}
-
-void hsv_to_rgb(vec4 hsv, out vec4 outcol)
-{
- float i, f, p, q, t, h, s, v;
- vec3 rgb;
-
- h = hsv[0];
- s = hsv[1];
- v = hsv[2];
-
- if (s == 0.0) {
- rgb = vec3(v, v, v);
- }
- else {
- if (h == 1.0) {
- h = 0.0;
- }
-
- h *= 6.0;
- i = floor(h);
- f = h - i;
- rgb = vec3(f, f, f);
- p = v * (1.0 - s);
- q = v * (1.0 - (s * f));
- t = v * (1.0 - (s * (1.0 - f)));
-
- if (i == 0.0) {
- rgb = vec3(v, t, p);
- }
- else if (i == 1.0) {
- rgb = vec3(q, v, p);
- }
- else if (i == 2.0) {
- rgb = vec3(p, v, t);
- }
- else if (i == 3.0) {
- rgb = vec3(p, q, v);
- }
- else if (i == 4.0) {
- rgb = vec3(t, p, v);
- }
- else {
- rgb = vec3(v, p, q);
- }
- }
-
- outcol = vec4(rgb, hsv.w);
-}
-
-void color_to_normal_new_shading(vec3 color, out vec3 normal)
-{
- normal = vec3(2.0) * color - vec3(1.0);
-}
-
-void color_to_blender_normal_new_shading(vec3 color, out vec3 normal)
-{
- normal = vec3(2.0, -2.0, -2.0) * color - vec3(1.0);
-}
-
-#ifndef M_PI
-# define M_PI 3.14159265358979323846
-#endif
-#ifndef M_1_PI
-# define M_1_PI 0.318309886183790671538
-#endif
-
-/*********** SHADER NODES ***************/
-
-void particle_info(vec4 sprops,
- vec4 loc,
- vec3 vel,
- vec3 avel,
- out float index,
- out float random,
- out float age,
- out float life_time,
- out vec3 location,
- out float size,
- out vec3 velocity,
- out vec3 angular_velocity)
-{
- index = sprops.x;
- random = loc.w;
- age = sprops.y;
- life_time = sprops.z;
- size = sprops.w;
-
- location = loc.xyz;
- velocity = vel;
- angular_velocity = avel;
-}
-
-void vect_normalize(vec3 vin, out vec3 vout)
-{
- vout = normalize(vin);
-}
-
-void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout)
-{
- vout = (mat * vec4(vin, 0.0)).xyz;
-}
-
-void normal_transform_transposed_m4v3(vec3 vin, mat4 mat, out vec3 vout)
-{
- vout = transpose(mat3(mat)) * vin;
-}
-
-void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout)
-{
- vout = (mat * vec4(vin, 1.0)).xyz;
-}
-
-void point_texco_remap_square(vec3 vin, out vec3 vout)
-{
- vout = vin * 2.0 - 1.0;
-}
-
-void point_texco_clamp(vec3 vin, sampler2D ima, out vec3 vout)
-{
- vec2 half_texel_size = 0.5 / vec2(textureSize(ima, 0).xy);
- vout = clamp(vin, half_texel_size.xyy, 1.0 - half_texel_size.xyy);
-}
-
-void point_map_to_sphere(vec3 vin, out vec3 vout)
-{
- float len = length(vin);
- float v, u;
- if (len > 0.0) {
- if (vin.x == 0.0 && vin.y == 0.0) {
- u = 0.0;
- }
- else {
- u = (1.0 - atan(vin.x, vin.y) / M_PI) / 2.0;
- }
-
- v = 1.0 - acos(vin.z / len) / M_PI;
- }
- else {
- v = u = 0.0;
- }
-
- vout = vec3(u, v, 0.0);
-}
-
-void point_map_to_tube(vec3 vin, out vec3 vout)
-{
- float u, v;
- v = (vin.z + 1.0) * 0.5;
- float len = sqrt(vin.x * vin.x + vin.y * vin[1]);
- if (len > 0.0) {
- u = (1.0 - (atan(vin.x / len, vin.y / len) / M_PI)) * 0.5;
- }
- else {
- v = u = 0.0;
- }
-
- vout = vec3(u, v, 0.0);
-}
-
-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;
- outvec = clamp(outvec, minvec, maxvec);
-}
-
-void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist)
-{
- outdepth = abs(co.z);
- outdist = length(co);
- outview = normalize(co);
-}
-
-void math_add(float val1, float val2, out float outval)
-{
- outval = val1 + val2;
-}
-
-void math_subtract(float val1, float val2, out float outval)
-{
- outval = val1 - val2;
-}
-
-void math_multiply(float val1, float val2, out float outval)
-{
- outval = val1 * val2;
-}
-
-void math_divide(float val1, float val2, out float outval)
-{
- if (val2 == 0.0) {
- outval = 0.0;
- }
- else {
- outval = val1 / val2;
- }
-}
-
-void math_sine(float val, out float outval)
-{
- outval = sin(val);
-}
-
-void math_cosine(float val, out float outval)
-{
- outval = cos(val);
-}
-
-void math_tangent(float val, out float outval)
-{
- outval = tan(val);
-}
-
-void math_asin(float val, out float outval)
-{
- if (val <= 1.0 && val >= -1.0) {
- outval = asin(val);
- }
- else {
- outval = 0.0;
- }
-}
-
-void math_acos(float val, out float outval)
-{
- if (val <= 1.0 && val >= -1.0) {
- outval = acos(val);
- }
- else {
- outval = 0.0;
- }
-}
-
-void math_atan(float val, out float outval)
-{
- outval = atan(val);
-}
-
-void math_pow(float val1, float val2, out float outval)
-{
- if (val1 >= 0.0) {
- outval = compatible_pow(val1, val2);
- }
- else {
- float val2_mod_1 = mod(abs(val2), 1.0);
-
- if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001) {
- outval = compatible_pow(val1, floor(val2 + 0.5));
- }
- else {
- outval = 0.0;
- }
- }
-}
-
-void math_log(float val1, float val2, out float outval)
-{
- if (val1 > 0.0 && val2 > 0.0) {
- outval = log2(val1) / log2(val2);
- }
- else {
- outval = 0.0;
- }
-}
-
-void math_max(float val1, float val2, out float outval)
-{
- outval = max(val1, val2);
-}
-
-void math_min(float val1, float val2, out float outval)
-{
- outval = min(val1, val2);
-}
-
-void math_round(float val, out float outval)
-{
- outval = floor(val + 0.5);
-}
-
-void math_less_than(float val1, float val2, out float outval)
-{
- if (val1 < val2) {
- outval = 1.0;
- }
- else {
- outval = 0.0;
- }
-}
-
-void math_greater_than(float val1, float val2, out float outval)
-{
- if (val1 > val2) {
- outval = 1.0;
- }
- else {
- outval = 0.0;
- }
-}
-
-void math_modulo(float val1, float val2, out float outval)
-{
- if (val2 == 0.0 || val1 == val2) {
- outval = 0.0;
- }
- else {
- /* change sign to match C convention, mod in GLSL will take absolute for negative numbers,
- * see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */
- outval = sign(val1) * mod(abs(val1), val2);
- }
-}
-
-void math_abs(float val1, out float outval)
-{
- outval = abs(val1);
-}
-
-void math_atan2(float val1, float val2, out float outval)
-{
- outval = atan(val1, val2);
-}
-
-void math_floor(float val, out float outval)
-{
- outval = floor(val);
-}
-
-void math_ceil(float val, out float outval)
-{
- outval = ceil(val);
-}
-
-void math_fract(float val, out float outval)
-{
- outval = val - floor(val);
-}
-
-void math_sqrt(float val, out float outval)
-{
- if (val > 0.0) {
- outval = sqrt(val);
- }
- else {
- outval = 0.0;
- }
-}
-
-void squeeze(float val, float width, float center, out float outval)
-{
- outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width)));
-}
-
-void map_range(
- float value, float fromMin, float fromMax, float toMin, float toMax, out float result)
-{
- if (fromMax != fromMin) {
- result = toMin + ((value - fromMin) / (fromMax - fromMin)) * (toMax - toMin);
- }
- else {
- result = 0.0;
- }
-}
-
-void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
-{
- outvec = v1 + v2;
- outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333;
-}
-
-void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
-{
- outvec = v1 - v2;
- outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333;
-}
-
-void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
-{
- outvec = v1 + v2;
- outval = length(outvec);
- outvec = normalize(outvec);
-}
-void vec_math_mix(float strength, vec3 v1, vec3 v2, out vec3 outvec)
-{
- outvec = strength * v1 + (1 - strength) * v2;
-}
-
-void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
-{
- outvec = vec3(0);
- outval = dot(v1, v2);
-}
-
-void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
-{
- outvec = cross(v1, v2);
- outval = length(outvec);
- outvec /= outval;
-}
-
-void vec_math_normalize(vec3 v, out vec3 outvec, out float outval)
-{
- outval = length(v);
- outvec = normalize(v);
-}
-
-void vec_math_negate(vec3 v, out vec3 outv)
-{
- outv = -v;
-}
-
-void invert_z(vec3 v, out vec3 outv)
-{
- v.z = -v.z;
- outv = v;
-}
-
-void normal_new_shading(vec3 nor, vec3 dir, out vec3 outnor, out float outdot)
-{
- outnor = dir;
- outdot = dot(normalize(nor), dir);
-}
-
-void curves_vec(float fac, vec3 vec, sampler1DArray curvemap, float layer, out vec3 outvec)
-{
- 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);
-}
-
-/* ext is vec4(in_x, in_dy, out_x, out_dy). */
-float curve_extrapolate(float x, float y, vec4 ext)
-{
- if (x < 0.0) {
- return y + x * ext.y;
- }
- else if (x > 1.0) {
- return y + (x - 1.0) * ext.w;
- }
- else {
- return y;
- }
-}
-
-#define RANGE_RESCALE(x, min, range) ((x - min) * range)
-
-void curves_rgb(float fac,
- vec4 col,
- sampler1DArray curvemap,
- float layer,
- vec4 range,
- vec4 ext_r,
- vec4 ext_g,
- vec4 ext_b,
- vec4 ext_a,
- out vec4 outcol)
-{
- vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer);
- vec3 samp;
- samp.r = texture(curvemap, co.xw).a;
- samp.g = texture(curvemap, co.yw).a;
- samp.b = texture(curvemap, co.zw).a;
-
- samp.r = curve_extrapolate(co.x, samp.r, ext_a);
- samp.g = curve_extrapolate(co.y, samp.g, ext_a);
- samp.b = curve_extrapolate(co.z, samp.b, ext_a);
-
- vec3 rgb_min = vec3(ext_r.x, ext_g.x, ext_b.x);
- co.xyz = RANGE_RESCALE(samp.rgb, rgb_min, range.rgb);
-
- samp.r = texture(curvemap, co.xw).r;
- samp.g = texture(curvemap, co.yw).g;
- samp.b = texture(curvemap, co.zw).b;
-
- outcol.r = curve_extrapolate(co.x, samp.r, ext_r);
- outcol.g = curve_extrapolate(co.y, samp.g, ext_g);
- outcol.b = curve_extrapolate(co.z, samp.b, ext_b);
- outcol.a = col.a;
-
- outcol = mix(col, outcol, fac);
-}
-
-void curves_rgb_opti(float fac,
- vec4 col,
- sampler1DArray curvemap,
- float layer,
- vec4 range,
- vec4 ext_a,
- out vec4 outcol)
-{
- vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer);
- vec3 samp;
- samp.r = texture(curvemap, co.xw).a;
- samp.g = texture(curvemap, co.yw).a;
- samp.b = texture(curvemap, co.zw).a;
-
- outcol.r = curve_extrapolate(co.x, samp.r, ext_a);
- outcol.g = curve_extrapolate(co.y, samp.g, ext_a);
- outcol.b = curve_extrapolate(co.z, samp.b, ext_a);
- outcol.a = col.a;
-
- outcol = mix(col, outcol, fac);
-}
-
-void set_value(float val, out float outval)
-{
- outval = val;
-}
-
-void set_rgb(vec3 col, out vec3 outcol)
-{
- outcol = col;
-}
-
-void set_rgba(vec4 col, out vec4 outcol)
-{
- outcol = col;
-}
-
-void set_value_zero(out float outval)
-{
- outval = 0.0;
-}
-
-void set_value_one(out float outval)
-{
- outval = 1.0;
-}
-
-void set_rgb_zero(out vec3 outval)
-{
- outval = vec3(0.0);
-}
-
-void set_rgb_one(out vec3 outval)
-{
- outval = vec3(1.0);
-}
-
-void set_rgba_zero(out vec4 outval)
-{
- outval = vec4(0.0);
-}
-
-void set_rgba_one(out vec4 outval)
-{
- outval = vec4(1.0);
-}
-
-void brightness_contrast(vec4 col, float brightness, float contrast, out vec4 outcol)
-{
- float a = 1.0 + contrast;
- float b = brightness - contrast * 0.5;
-
- outcol.r = max(a * col.r + b, 0.0);
- outcol.g = max(a * col.g + b, 0.0);
- outcol.b = max(a * col.b + b, 0.0);
- outcol.a = col.a;
-}
-
-void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- outcol = mix(col1, col2, fac);
- outcol.a = col1.a;
-}
-
-void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- outcol = mix(col1, col1 + col2, fac);
- outcol.a = col1.a;
-}
-
-void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- outcol = mix(col1, col1 * col2, fac);
- outcol.a = col1.a;
-}
-
-void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- float facm = 1.0 - fac;
-
- outcol = vec4(1.0) - (vec4(facm) + fac * (vec4(1.0) - col2)) * (vec4(1.0) - col1);
- outcol.a = col1.a;
-}
-
-void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- float facm = 1.0 - fac;
-
- outcol = col1;
-
- if (outcol.r < 0.5) {
- outcol.r *= facm + 2.0 * fac * col2.r;
- }
- else {
- outcol.r = 1.0 - (facm + 2.0 * fac * (1.0 - col2.r)) * (1.0 - outcol.r);
- }
-
- if (outcol.g < 0.5) {
- outcol.g *= facm + 2.0 * fac * col2.g;
- }
- else {
- outcol.g = 1.0 - (facm + 2.0 * fac * (1.0 - col2.g)) * (1.0 - outcol.g);
- }
-
- if (outcol.b < 0.5) {
- outcol.b *= facm + 2.0 * fac * col2.b;
- }
- else {
- outcol.b = 1.0 - (facm + 2.0 * fac * (1.0 - col2.b)) * (1.0 - outcol.b);
- }
-}
-
-void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- outcol = mix(col1, col1 - col2, fac);
- outcol.a = col1.a;
-}
-
-void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- float facm = 1.0 - fac;
-
- outcol = col1;
-
- if (col2.r != 0.0) {
- outcol.r = facm * outcol.r + fac * outcol.r / col2.r;
- }
- if (col2.g != 0.0) {
- outcol.g = facm * outcol.g + fac * outcol.g / col2.g;
- }
- if (col2.b != 0.0) {
- outcol.b = facm * outcol.b + fac * outcol.b / col2.b;
- }
-}
-
-void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- outcol = mix(col1, abs(col1 - col2), fac);
- outcol.a = col1.a;
-}
-
-void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- outcol.rgb = min(col1.rgb, col2.rgb * fac);
- outcol.a = col1.a;
-}
-
-void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- outcol.rgb = max(col1.rgb, col2.rgb * fac);
- outcol.a = col1.a;
-}
-
-void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- outcol = col1;
-
- if (outcol.r != 0.0) {
- float tmp = 1.0 - fac * col2.r;
- if (tmp <= 0.0) {
- outcol.r = 1.0;
- }
- else if ((tmp = outcol.r / tmp) > 1.0) {
- outcol.r = 1.0;
- }
- else {
- outcol.r = tmp;
- }
- }
- if (outcol.g != 0.0) {
- float tmp = 1.0 - fac * col2.g;
- if (tmp <= 0.0) {
- outcol.g = 1.0;
- }
- else if ((tmp = outcol.g / tmp) > 1.0) {
- outcol.g = 1.0;
- }
- else {
- outcol.g = tmp;
- }
- }
- if (outcol.b != 0.0) {
- float tmp = 1.0 - fac * col2.b;
- if (tmp <= 0.0) {
- outcol.b = 1.0;
- }
- else if ((tmp = outcol.b / tmp) > 1.0) {
- outcol.b = 1.0;
- }
- else {
- outcol.b = tmp;
- }
- }
-}
-
-void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- float tmp, facm = 1.0 - fac;
-
- outcol = col1;
-
- tmp = facm + fac * col2.r;
- if (tmp <= 0.0) {
- outcol.r = 0.0;
- }
- else if ((tmp = (1.0 - (1.0 - outcol.r) / tmp)) < 0.0) {
- outcol.r = 0.0;
- }
- else if (tmp > 1.0) {
- outcol.r = 1.0;
- }
- else {
- outcol.r = tmp;
- }
-
- tmp = facm + fac * col2.g;
- if (tmp <= 0.0) {
- outcol.g = 0.0;
- }
- else if ((tmp = (1.0 - (1.0 - outcol.g) / tmp)) < 0.0) {
- outcol.g = 0.0;
- }
- else if (tmp > 1.0) {
- outcol.g = 1.0;
- }
- else {
- outcol.g = tmp;
- }
-
- tmp = facm + fac * col2.b;
- if (tmp <= 0.0) {
- outcol.b = 0.0;
- }
- else if ((tmp = (1.0 - (1.0 - outcol.b) / tmp)) < 0.0) {
- outcol.b = 0.0;
- }
- else if (tmp > 1.0) {
- outcol.b = 1.0;
- }
- else {
- outcol.b = tmp;
- }
-}
-
-void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- float facm = 1.0 - fac;
-
- outcol = col1;
-
- vec4 hsv, hsv2, tmp;
- rgb_to_hsv(col2, hsv2);
-
- if (hsv2.y != 0.0) {
- rgb_to_hsv(outcol, hsv);
- hsv.x = hsv2.x;
- hsv_to_rgb(hsv, tmp);
-
- outcol = mix(outcol, tmp, fac);
- outcol.a = col1.a;
- }
-}
-
-void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- float facm = 1.0 - fac;
-
- outcol = col1;
-
- vec4 hsv, hsv2;
- rgb_to_hsv(outcol, hsv);
-
- if (hsv.y != 0.0) {
- rgb_to_hsv(col2, hsv2);
-
- hsv.y = facm * hsv.y + fac * hsv2.y;
- hsv_to_rgb(hsv, outcol);
- }
-}
-
-void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- float facm = 1.0 - fac;
-
- vec4 hsv, hsv2;
- rgb_to_hsv(col1, hsv);
- rgb_to_hsv(col2, hsv2);
-
- hsv.z = facm * hsv.z + fac * hsv2.z;
- hsv_to_rgb(hsv, outcol);
-}
-
-void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- float facm = 1.0 - fac;
-
- outcol = col1;
-
- vec4 hsv, hsv2, tmp;
- rgb_to_hsv(col2, hsv2);
-
- if (hsv2.y != 0.0) {
- rgb_to_hsv(outcol, hsv);
- hsv.x = hsv2.x;
- hsv.y = hsv2.y;
- hsv_to_rgb(hsv, tmp);
-
- outcol = mix(outcol, tmp, fac);
- outcol.a = col1.a;
- }
-}
-
-void mix_soft(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
- float facm = 1.0 - fac;
-
- vec4 one = vec4(1.0);
- vec4 scr = one - (one - col2) * (one - col1);
- outcol = facm * col1 + fac * ((one - col1) * col2 * col1 + col1 * scr);
-}
-
-void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
-{
- fac = clamp(fac, 0.0, 1.0);
-
- outcol = col1 + fac * (2.0 * (col2 - vec4(0.5)));
-}
-
-void valtorgb_opti_constant(
- float fac, float edge, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha)
-{
- outcol = (fac > edge) ? color2 : color1;
- outalpha = outcol.a;
-}
-
-void valtorgb_opti_linear(
- float fac, vec2 mulbias, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha)
-{
- fac = clamp(fac * mulbias.x + mulbias.y, 0.0, 1.0);
- outcol = mix(color1, color2, fac);
- outalpha = outcol.a;
-}
-
-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)
-{
- fac = clamp(fac, 0.0, 1.0);
- outcol = texelFetch(colormap, ivec2(fac * (textureSize(colormap, 0).x - 1), layer), 0);
- outalpha = outcol.a;
-}
-
-void rgbtobw(vec4 color, out float outval)
-{
- vec3 factors = vec3(0.2126, 0.7152, 0.0722);
- outval = dot(color.rgb, factors);
-}
-
-void invert(float fac, vec4 col, out vec4 outcol)
-{
- outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac);
- outcol.w = col.w;
-}
-
-void clamp_vec3(vec3 vec, vec3 min, vec3 max, out vec3 out_vec)
-{
- out_vec = clamp(vec, min, max);
-}
-
-void clamp_value(float value, float min, float max, out float result)
-{
- result = clamp(value, min, max);
-}
-
-void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol)
-{
- vec4 hsv;
-
- rgb_to_hsv(col, hsv);
-
- hsv[0] = fract(hsv[0] + hue + 0.5);
- hsv[1] = clamp(hsv[1] * sat, 0.0, 1.0);
- hsv[2] = hsv[2] * value;
-
- hsv_to_rgb(hsv, outcol);
-
- outcol = mix(col, outcol, fac);
-}
-
-void separate_rgb(vec4 col, out float r, out float g, out float b)
-{
- r = col.r;
- g = col.g;
- b = col.b;
-}
-
-void combine_rgb(float r, float g, float b, out vec4 col)
-{
- col = vec4(r, g, b, 1.0);
-}
-
-void separate_xyz(vec3 vec, out float x, out float y, out float z)
-{
- x = vec.r;
- y = vec.g;
- z = vec.b;
-}
-
-void combine_xyz(float x, float y, float z, out vec3 vec)
-{
- vec = vec3(x, y, z);
-}
-
-void separate_hsv(vec4 col, out float h, out float s, out float v)
-{
- vec4 hsv;
-
- rgb_to_hsv(col, hsv);
- h = hsv[0];
- s = hsv[1];
- v = hsv[2];
-}
-
-void combine_hsv(float h, float s, float v, out vec4 col)
-{
- hsv_to_rgb(vec4(h, s, v, 1.0), col);
-}
-
-void output_node(vec4 rgb, float alpha, out vec4 outrgb)
-{
- outrgb = vec4(rgb.rgb, alpha);
-}
-
-/*********** TEXTURES ***************/
-
-void texco_norm(vec3 normal, out vec3 outnormal)
-{
- /* corresponds to shi->orn, which is negated so cancels
- out blender normal negation */
- outnormal = normalize(normal);
-}
-
-vec3 mtex_2d_mapping(vec3 vec)
-{
- return vec3(vec.xy * 0.5 + vec2(0.5), vec.z);
-}
-
-/** helper method to extract the upper left 3x3 matrix from a 4x4 matrix */
-mat3 to_mat3(mat4 m4)
-{
- mat3 m3;
- m3[0] = m4[0].xyz;
- m3[1] = m4[1].xyz;
- m3[2] = m4[2].xyz;
- return m3;
-}
-
-/*********** NEW SHADER UTILITIES **************/
-
-float fresnel_dielectric_0(float eta)
-{
- /* compute fresnel reflactance at normal incidence => cosi = 1.0 */
- float A = (eta - 1.0) / (eta + 1.0);
-
- return A * A;
-}
-
-float fresnel_dielectric_cos(float cosi, float eta)
-{
- /* compute fresnel reflectance without explicitly computing
- * the refracted direction */
- float c = abs(cosi);
- float g = eta * eta - 1.0 + c * c;
- float result;
-
- if (g > 0.0) {
- g = sqrt(g);
- float A = (g - c) / (g + c);
- float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0);
- result = 0.5 * A * A * (1.0 + B * B);
- }
- else {
- result = 1.0; /* TIR (no refracted component) */
- }
-
- return result;
-}
-
-float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
-{
- /* compute fresnel reflectance without explicitly computing
- * the refracted direction */
- return fresnel_dielectric_cos(dot(Incoming, Normal), eta);
-}
-
-float hypot(float x, float y)
-{
- return sqrt(x * x + y * y);
-}
-
-void generated_from_orco(vec3 orco, out vec3 generated)
-{
-#ifdef VOLUMETRICS
-# ifdef MESH_SHADER
- generated = volumeObjectLocalCoord;
-# else
- generated = worldPosition;
-# endif
-#else
- generated = orco;
-#endif
-}
-
-int floor_to_int(float x)
-{
- return int(floor(x));
-}
-
-int quick_floor(float x)
-{
- return int(x) - ((x < 0) ? 1 : 0);
-}
-
-float integer_noise(int n)
-{
- int nn;
- n = (n + 1013) & 0x7fffffff;
- n = (n >> 13) ^ n;
- nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
- return 0.5 * (float(nn) / 1073741824.0);
-}
-
-uint hash(uint kx, uint ky, uint kz)
-{
-#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
-#define final(a, b, c) \
- { \
- c ^= b; \
- c -= rot(b, 14); \
- a ^= c; \
- a -= rot(c, 11); \
- b ^= a; \
- b -= rot(a, 25); \
- c ^= b; \
- c -= rot(b, 16); \
- a ^= c; \
- a -= rot(c, 4); \
- b ^= a; \
- b -= rot(a, 14); \
- c ^= b; \
- c -= rot(b, 24); \
- }
- // now hash the data!
- uint a, b, c, len = 3u;
- a = b = c = 0xdeadbeefu + (len << 2u) + 13u;
-
- c += kz;
- b += ky;
- a += kx;
- final(a, b, c);
-
- return c;
-#undef rot
-#undef final
-}
-
-uint hash(int kx, int ky, int kz)
-{
- return hash(uint(kx), uint(ky), uint(kz));
-}
-
-float bits_to_01(uint bits)
-{
- return (float(bits) / 4294967295.0);
-}
-
-float cellnoise(vec3 p)
-{
- int ix = quick_floor(p.x);
- int iy = quick_floor(p.y);
- int iz = quick_floor(p.z);
-
- return bits_to_01(hash(uint(ix), uint(iy), uint(iz)));
-}
-
-vec3 cellnoise_color(vec3 p)
-{
- float r = cellnoise(p.xyz);
- float g = cellnoise(p.yxz);
- float b = cellnoise(p.yzx);
-
- return vec3(r, g, b);
-}
-
-float floorfrac(float x, out int i)
-{
- float x_floor = floor(x);
- i = int(x_floor);
- return x - x_floor;
-}
-
-/* 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,
- vec3 basecol_tint,
- float metallic,
- float specular_fac,
- float specular_tint,
- out vec3 diffuse,
- out vec3 f0)
-{
- 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;
- /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps,
- * therefore we need to clamp value. */
- f = clamp(f, 0.0, 1.0);
- /* 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
-void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
-{
- N = normalize(N);
- result = CLOSURE_DEFAULT;
- eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance);
- closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
- result.radiance *= color.rgb;
-}
-
-void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result)
-{
- N = normalize(N);
- vec3 out_spec, ssr_spec;
- eevee_closure_glossy(N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
- vec3 vN = mat3(ViewMatrix) * N;
- result = CLOSURE_DEFAULT;
- result.radiance = out_spec * color.rgb;
- closure_load_ssr_data(ssr_spec * color.rgb, roughness, N, viewCameraVec, int(ssr_id), result);
-}
-
-void node_bsdf_anisotropic(vec4 color,
- float roughness,
- float anisotropy,
- float rotation,
- vec3 N,
- vec3 T,
- out Closure 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)
-{
- N = normalize(N);
- vec3 out_spec, out_refr, ssr_spec;
- vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb :
- color.rgb; /* Simulate 2 transmission event */
- eevee_closure_glass(
- N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
- out_refr *= refr_color;
- out_spec *= color.rgb;
- float fresnel = F_eta(ior, dot(N, cameraVec));
- vec3 vN = mat3(ViewMatrix) * N;
- result = CLOSURE_DEFAULT;
- result.radiance = mix(out_refr, out_spec, fresnel);
- closure_load_ssr_data(
- ssr_spec * color.rgb * fresnel, roughness, N, viewCameraVec, int(ssr_id), result);
-}
-
-void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result)
-{
- node_bsdf_diffuse(color, 0.0, N, 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,
- vec4 emission,
- float alpha,
- vec3 N,
- vec3 CN,
- vec3 T,
- vec3 I,
- float ssr_id,
- float sss_id,
- vec3 sss_scale,
- out Closure result)
-{
- N = normalize(N);
- 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;
- 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);
-
- /* 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);
-
- vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
-
- vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
-
- float sss_scalef = avg(sss_scale) * subsurface;
- eevee_closure_principled(N,
- mixed_ss_base_color,
- f0,
- f90,
- 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;
-
- result = CLOSURE_DEFAULT;
- result.radiance = out_spec + out_refr;
- result.radiance += out_diff * out_sheen; /* Coarse approx. */
-
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
-
- vec3 sss_radiance = (out_diff + out_trans) * alpha;
-# ifndef USE_SSS
- result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission);
-# else
-# ifdef USE_SSS_ALBEDO
- vec3 sss_albedo = mixed_ss_base_color;
-# else
- sss_radiance *= mixed_ss_base_color;
-# endif
- sss_radiance *= (1.0 - transmission);
- closure_load_sss_data(sss_scalef,
- sss_radiance,
-# ifdef USE_SSS_ALBEDO
- sss_albedo,
-# endif
- int(sss_id),
- result);
-# endif /* USE_SSS */
-
- result.radiance += emission.rgb;
- result.radiance *= alpha;
- result.transmittance = vec3(1.0 - alpha);
-}
-
-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,
- vec4 emission,
- float alpha,
- vec3 N,
- vec3 CN,
- vec3 T,
- vec3 I,
- float ssr_id,
- float sss_id,
- vec3 sss_scale,
- out Closure result)
-{
- N = normalize(N);
- metallic = saturate(metallic);
- float dielectric = 1.0 - metallic;
-
- 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, vec3(1.0), int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec);
-
- result = CLOSURE_DEFAULT;
- result.radiance = out_spec + out_diff * (diffuse + out_sheen);
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
- result.radiance += emission.rgb;
- result.radiance *= alpha;
- result.transmittance = vec3(1.0 - alpha);
-}
-
-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,
- vec4 emission,
- float alpha,
- vec3 N,
- vec3 CN,
- vec3 T,
- vec3 I,
- float ssr_id,
- float sss_id,
- vec3 sss_scale,
- out Closure result)
-{
- N = normalize(N);
- vec3 out_spec, ssr_spec;
-
- vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
-
- eevee_closure_glossy(N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
-
- result = CLOSURE_DEFAULT;
- result.radiance = out_spec;
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
- result.radiance += emission.rgb;
- result.radiance *= alpha;
- result.transmittance = vec3(1.0 - alpha);
-}
-
-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,
- vec4 emission,
- float alpha,
- 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;
- N = normalize(N);
-
- vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
-
- eevee_closure_clearcoat(N,
- base_color.rgb,
- f90,
- int(ssr_id),
- roughness,
- CN,
- clearcoat * 0.25,
- clearcoat_roughness,
- 1.0,
- out_spec,
- ssr_spec);
-
- result = CLOSURE_DEFAULT;
- result.radiance = out_spec;
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
- result.radiance += emission.rgb;
- result.radiance *= alpha;
- result.transmittance = vec3(1.0 - alpha);
-}
-
-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,
- vec4 emission,
- float alpha,
- vec3 N,
- vec3 CN,
- vec3 T,
- vec3 I,
- float ssr_id,
- float sss_id,
- vec3 sss_scale,
- out Closure result)
-{
- metallic = saturate(metallic);
- N = normalize(N);
-
- 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 = avg(sss_scale) * subsurface;
-
- float NV = dot(N, cameraVec);
- vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
-
- vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
-
- eevee_closure_skin(N,
- mixed_ss_base_color,
- f0,
- f90,
- int(ssr_id),
- roughness,
- 1.0,
- sss_scalef,
- out_diff,
- out_trans,
- out_spec,
- ssr_spec);
-
- result = CLOSURE_DEFAULT;
- result.radiance = out_spec;
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
-
- vec3 sss_radiance = (out_diff + out_trans) * alpha;
-# ifndef USE_SSS
- result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission);
-# else
-# ifdef USE_SSS_ALBEDO
- vec3 sss_albedo = mixed_ss_base_color;
-# else
- sss_radiance *= mixed_ss_base_color;
-# endif
- sss_radiance *= (1.0 - transmission);
- closure_load_sss_data(sss_scalef,
- sss_radiance,
-# ifdef USE_SSS_ALBEDO
- sss_albedo,
-# endif
- int(sss_id),
- result);
-# endif /* USE_SSS */
-
- result.radiance += out_diff * out_sheen;
- result.radiance += emission.rgb;
- result.radiance *= alpha;
- result.transmittance = vec3(1.0 - alpha);
-}
-
-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,
- vec4 emission,
- float alpha,
- 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);
- N = normalize(N);
-
- 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), 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;
-
- result = CLOSURE_DEFAULT;
- result.radiance = mix(out_refr, out_spec, fresnel);
- closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
- result.radiance += emission.rgb;
- result.radiance *= alpha;
- result.transmittance = vec3(1.0 - alpha);
-}
-
-void node_bsdf_translucent(vec4 color, vec3 N, out Closure result)
-{
- node_bsdf_diffuse(color, 0.0, -N, result);
-}
-
-void node_bsdf_transparent(vec4 color, out Closure result)
-{
- result = CLOSURE_DEFAULT;
- result.radiance = vec3(0.0);
- result.transmittance = abs(color.rgb);
-}
-
-void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result)
-{
- node_bsdf_diffuse(color, 0.0, N, result);
-}
-
-void node_subsurface_scattering(vec4 color,
- float scale,
- vec3 radius,
- float sharpen,
- float texture_blur,
- vec3 N,
- float sss_id,
- out Closure result)
-{
-# if defined(USE_SSS)
- N = normalize(N);
- vec3 out_diff, out_trans;
- vec3 vN = mat3(ViewMatrix) * N;
- result = CLOSURE_DEFAULT;
- closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
-
- eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans);
-
- vec3 sss_radiance = out_diff + out_trans;
-# ifdef USE_SSS_ALBEDO
- /* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */
- vec3 sss_albedo = mix(color.rgb, vec3(1.0), texture_blur);
- sss_radiance *= mix(vec3(1.0), color.rgb, texture_blur);
-# else
- sss_radiance *= color.rgb;
-# endif
- closure_load_sss_data(scale,
- sss_radiance,
-# ifdef USE_SSS_ALBEDO
- sss_albedo,
-# endif
- int(sss_id),
- result);
-# else
- node_bsdf_diffuse(color, 0.0, N, result);
-# endif
-}
-
-void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result)
-{
- N = normalize(N);
- vec3 out_refr;
- color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */
- eevee_closure_refraction(N, roughness, ior, out_refr);
- vec3 vN = mat3(ViewMatrix) * N;
- result = CLOSURE_DEFAULT;
- result.ssr_normal = normal_encode(vN, viewCameraVec);
- result.radiance = out_refr * color.rgb;
-}
-
-void node_ambient_occlusion(
- vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao)
-{
- vec3 bent_normal;
- vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
- result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal);
- result_color = result_ao * color;
-}
-
-void node_wireframe(float size, vec2 barycentric, vec3 barycentric_dist, out float fac)
-{
- vec3 barys = barycentric.xyy;
- barys.z = 1.0 - barycentric.x - barycentric.y;
-
- size *= 0.5;
- vec3 s = step(-size, -barys * barycentric_dist);
-
- fac = max(s.x, max(s.y, s.z));
-}
-
-void node_wireframe_screenspace(float size, vec2 barycentric, out float fac)
-{
- vec3 barys = barycentric.xyy;
- barys.z = 1.0 - barycentric.x - barycentric.y;
-
- size *= (1.0 / 3.0);
- vec3 dx = dFdx(barys);
- vec3 dy = dFdy(barys);
- vec3 deltas = sqrt(dx * dx + dy * dy);
-
- vec3 s = step(-deltas * size, -barys);
-
- fac = max(s.x, max(s.y, s.z));
-}
-
-#else /* VOLUMETRICS */
-
-/* Stub all bsdf functions not compatible with volumetrics. */
-# define node_bsdf_diffuse
-# define node_bsdf_glossy
-# define node_bsdf_anisotropic
-# define node_bsdf_glass
-# define node_bsdf_toon
-# define node_bsdf_principled
-# define node_bsdf_principled_dielectric
-# define node_bsdf_principled_metallic
-# define node_bsdf_principled_clearcoat
-# define node_bsdf_principled_subsurface
-# define node_bsdf_principled_glass
-# define node_bsdf_translucent
-# define node_bsdf_transparent
-# define node_bsdf_velvet
-# define node_subsurface_scattering
-# define node_bsdf_refraction
-# define node_ambient_occlusion
-# define node_wireframe
-# define node_wireframe_screenspace
-
-#endif /* VOLUMETRICS */
-
-/* emission */
-
-void node_emission(vec4 color, float strength, vec3 vN, out Closure result)
-{
- result = CLOSURE_DEFAULT;
-#ifndef VOLUMETRICS
- result.radiance = color.rgb * strength;
- result.ssr_normal = normal_encode(vN, viewCameraVec);
-#else
- result.emission = color.rgb * strength;
-#endif
-}
-
-/* background */
-
-void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec)
-{
-#ifdef MESH_SHADER
- worldvec = worldPosition;
-#else
- vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (ProjectionMatrixInverse * v);
-
- vec3 co = co_homogenous.xyz / co_homogenous.w;
-# if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
- worldvec = mat3(ViewMatrixInverse) * co;
-# else
- worldvec = mat3(ModelMatrixInverse) * (mat3(ViewMatrixInverse) * co);
-# endif
-#endif
-}
-
-void node_background(vec4 color, float strength, out Closure result)
-{
-#ifndef VOLUMETRICS
- color *= strength;
- result = CLOSURE_DEFAULT;
- result.radiance = color.rgb;
- result.transmittance = vec3(0.0);
-#else
- result = CLOSURE_DEFAULT;
-#endif
-}
-
-/* volumes */
-
-void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result)
-{
-#ifdef VOLUMETRICS
- result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy);
-#else
- result = CLOSURE_DEFAULT;
-#endif
-}
-
-void node_volume_absorption(vec4 color, float density, out Closure result)
-{
-#ifdef VOLUMETRICS
- result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0);
-#else
- result = CLOSURE_DEFAULT;
-#endif
-}
-
-void node_blackbody(float temperature, sampler1DArray spectrummap, float layer, out vec4 color)
-{
- if (temperature >= 12000.0) {
- color = vec4(0.826270103, 0.994478524, 1.56626022, 1.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, layer)).rgb, 1.0);
- }
-}
-
-void node_volume_principled(vec4 color,
- float density,
- float anisotropy,
- vec4 absorption_color,
- float emission_strength,
- vec4 emission_color,
- float blackbody_intensity,
- vec4 blackbody_tint,
- float temperature,
- float density_attribute,
- vec4 color_attribute,
- float temperature_attribute,
- sampler1DArray spectrummap,
- float layer,
- out Closure result)
-{
-#ifdef VOLUMETRICS
- vec3 absorption_coeff = vec3(0.0);
- vec3 scatter_coeff = vec3(0.0);
- vec3 emission_coeff = vec3(0.0);
-
- /* Compute density. */
- density = max(density, 0.0);
-
- if (density > 1e-5) {
- density = max(density * density_attribute, 0.0);
- }
-
- if (density > 1e-5) {
- /* Compute scattering and absorption coefficients. */
- vec3 scatter_color = color.rgb * color_attribute.rgb;
-
- scatter_coeff = scatter_color * density;
- absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0));
- absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) *
- density;
- }
-
- /* Compute emission. */
- emission_strength = max(emission_strength, 0.0);
-
- if (emission_strength > 1e-5) {
- emission_coeff += emission_strength * emission_color.rgb;
- }
-
- if (blackbody_intensity > 1e-3) {
- /* Add temperature from attribute. */
- float T = max(temperature * max(temperature_attribute, 0.0), 0.0);
-
- /* Stefan-Boltzman law. */
- float T2 = T * T;
- float T4 = T2 * T2;
- float sigma = 5.670373e-8 * 1e-6 / M_PI;
- float intensity = sigma * mix(1.0, T4, blackbody_intensity);
-
- if (intensity > 1e-5) {
- vec4 bb;
- node_blackbody(T, spectrummap, layer, bb);
- emission_coeff += bb.rgb * blackbody_tint.rgb * intensity;
- }
- }
-
- result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy);
-#else
- result = CLOSURE_DEFAULT;
-#endif
-}
-
-void node_holdout(out Closure result)
-{
- result = CLOSURE_DEFAULT;
-#ifndef VOLUMETRICS
- result.holdout = 1.0;
- result.flag = CLOSURE_HOLDOUT_FLAG;
-#endif
-}
-
-/* closures */
-
-void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader)
-{
- shader = closure_mix(shader1, shader2, fac);
-}
-
-void node_add_shader(Closure shader1, Closure shader2, out Closure shader)
-{
- shader = closure_add(shader1, shader2);
-}
-
-/* fresnel */
-
-void node_fresnel(float ior, vec3 N, vec3 I, out float result)
-{
- N = normalize(N);
- /* handle perspective/orthographic */
- vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
-
- float eta = max(ior, 0.00001);
- result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta);
-}
-
-/* layer_weight */
-
-void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing)
-{
- N = normalize(N);
-
- /* fresnel */
- float eta = max(1.0 - blend, 0.00001);
- vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
-
- fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta);
-
- /* facing */
- facing = abs(dot(I_view, N));
- if (blend != 0.5) {
- blend = clamp(blend, 0.0, 0.99999);
- blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend);
- facing = pow(facing, blend);
- }
- facing = 1.0 - facing;
-}
-
-/* gamma */
-
-void node_gamma(vec4 col, float gamma, out vec4 outcol)
-{
- outcol = col;
-
- if (col.r > 0.0) {
- outcol.r = compatible_pow(col.r, gamma);
- }
- if (col.g > 0.0) {
- outcol.g = compatible_pow(col.g, gamma);
- }
- if (col.b > 0.0) {
- outcol.b = compatible_pow(col.b, gamma);
- }
-}
-
-/* geometry */
-
-void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
-{
-#if defined(MESH_SHADER) && defined(VOLUMETRICS)
- vec3 cos = volumeObjectLocalCoord;
-#else
- vec3 cos = vec3(0.0);
-#endif
- outvec = texture(tex, cos).aaa;
- outcol = vec4(outvec, 1.0);
- outf = avg(outvec);
-}
-
-uniform vec3 volumeColor = vec3(1.0);
-
-void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
-{
-#if defined(MESH_SHADER) && defined(VOLUMETRICS)
- vec3 cos = volumeObjectLocalCoord;
-#else
- vec3 cos = vec3(0.0);
-#endif
-
- vec4 value = texture(tex, cos).rgba;
- /* Density is premultiplied for interpolation, divide it out here. */
- if (value.a > 1e-8) {
- value.rgb /= value.a;
- }
-
- outvec = value.rgb * volumeColor;
- outcol = vec4(outvec, 1.0);
- outf = avg(outvec);
-}
-
-void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
-{
-#if defined(MESH_SHADER) && defined(VOLUMETRICS)
- vec3 cos = volumeObjectLocalCoord;
-#else
- vec3 cos = vec3(0.0);
-#endif
- outf = texture(tex, cos).r;
- outvec = vec3(outf, outf, outf);
- outcol = vec4(outf, outf, outf, 1.0);
-}
-
-void node_attribute_volume_temperature(
- sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf)
-{
-#if defined(MESH_SHADER) && defined(VOLUMETRICS)
- vec3 cos = volumeObjectLocalCoord;
-#else
- vec3 cos = vec3(0.0);
-#endif
- float flame = texture(tex, cos).r;
-
- outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0;
- outvec = vec3(outf, outf, outf);
- outcol = vec4(outf, outf, outf, 1.0);
-}
-
-void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf)
-{
- outcol = vec4(attr, 1.0);
- outvec = attr;
- outf = avg(attr);
-}
-
-void node_uvmap(vec3 attr_uv, out vec3 outvec)
-{
- outvec = attr_uv;
-}
-
-void tangent_orco_x(vec3 orco_in, out vec3 orco_out)
-{
- orco_out = orco_in.xzy * vec3(0.0, -0.5, 0.5) + vec3(0.0, 0.25, -0.25);
-}
-
-void tangent_orco_y(vec3 orco_in, out vec3 orco_out)
-{
- orco_out = orco_in.zyx * vec3(-0.5, 0.0, 0.5) + vec3(0.25, 0.0, -0.25);
-}
-
-void tangent_orco_z(vec3 orco_in, out vec3 orco_out)
-{
- orco_out = orco_in.yxz * vec3(-0.5, 0.5, 0.0) + vec3(0.25, -0.25, 0.0);
-}
-
-void node_tangentmap(vec4 attr_tangent, out vec3 tangent)
-{
- tangent = normalize(attr_tangent.xyz);
-}
-
-void node_tangent(vec3 N, vec3 orco, mat4 objmat, out vec3 T)
-{
- T = (objmat * vec4(orco, 0.0)).xyz;
- T = cross(N, normalize(cross(T, N)));
-}
-
-void node_geometry(vec3 I,
- vec3 N,
- vec3 orco,
- mat4 objmat,
- mat4 toworld,
- vec2 barycentric,
- out vec3 position,
- out vec3 normal,
- out vec3 tangent,
- out vec3 true_normal,
- out vec3 incoming,
- out vec3 parametric,
- out float backfacing,
- out float pointiness)
-{
- /* handle perspective/orthographic */
- vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
- incoming = -(toworld * vec4(I_view, 0.0)).xyz;
-
-#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
- position = -incoming;
- true_normal = normal = incoming;
- tangent = parametric = vec3(0.0);
- vec3(0.0);
- backfacing = 0.0;
- pointiness = 0.0;
-#else
-
- position = worldPosition;
-# ifndef VOLUMETRICS
- normal = normalize(N);
- vec3 B = dFdx(worldPosition);
- vec3 T = dFdy(worldPosition);
- true_normal = normalize(cross(B, T));
-# else
- normal = (toworld * vec4(N, 0.0)).xyz;
- true_normal = normal;
-# endif
- tangent_orco_z(orco, orco);
- node_tangent(N, orco, objmat, tangent);
-
- parametric = vec3(barycentric, 0.0);
- backfacing = (gl_FrontFacing) ? 0.0 : 1.0;
- pointiness = 0.5;
-#endif
-}
-
-void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated)
-{
- vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (ProjectionMatrixInverse * v);
- vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
- co.xyz = normalize(co.xyz);
-#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
- generated = (ViewMatrixInverse * co).xyz;
-#else
- generated_from_orco(attr_orco, generated);
-#endif
-}
-
-void node_tex_coord(vec3 I,
- vec3 wN,
- mat4 obmatinv,
- vec4 camerafac,
- vec3 attr_orco,
- vec3 attr_uv,
- out vec3 generated,
- out vec3 normal,
- out vec3 uv,
- out vec3 object,
- out vec3 camera,
- out vec3 window,
- out vec3 reflection)
-{
- generated = attr_orco;
- normal = normalize(normal_world_to_object(wN));
- uv = attr_uv;
- object = (obmatinv * (ViewMatrixInverse * vec4(I, 1.0))).xyz;
- camera = vec3(I.xy, -I.z);
- vec4 projvec = ProjectionMatrix * vec4(I, 1.0);
- window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
- reflection = -reflect(cameraVec, normalize(wN));
-}
-
-void node_tex_coord_background(vec3 I,
- vec3 N,
- mat4 obmatinv,
- vec4 camerafac,
- vec3 attr_orco,
- vec3 attr_uv,
- out vec3 generated,
- out vec3 normal,
- out vec3 uv,
- out vec3 object,
- out vec3 camera,
- out vec3 window,
- out vec3 reflection)
-{
- vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
- vec4 co_homogenous = (ProjectionMatrixInverse * v);
-
- vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
-
- co = normalize(co);
-
- vec3 coords = (ViewMatrixInverse * co).xyz;
-
- generated = coords;
- normal = -coords;
- uv = vec3(attr_uv.xy, 0.0);
- object = (obmatinv * vec4(coords, 1.0)).xyz;
-
- camera = vec3(co.xy, -co.z);
- window = vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0);
-
- reflection = -coords;
-}
-
-#if defined(WORLD_BACKGROUND) || (defined(PROBE_CAPTURE) && !defined(MESH_SHADER))
-# define node_tex_coord node_tex_coord_background
-#endif
-
-/* textures */
-
-float calc_gradient(vec3 p, int gradient_type)
-{
- float x, y, z;
- x = p.x;
- y = p.y;
- z = p.z;
- if (gradient_type == 0) { /* linear */
- return x;
- }
- else if (gradient_type == 1) { /* quadratic */
- float r = max(x, 0.0);
- return r * r;
- }
- else if (gradient_type == 2) { /* easing */
- float r = min(max(x, 0.0), 1.0);
- float t = r * r;
- return (3.0 * t - 2.0 * t * r);
- }
- else if (gradient_type == 3) { /* diagonal */
- return (x + y) * 0.5;
- }
- else if (gradient_type == 4) { /* radial */
- return atan(y, x) / (M_PI * 2) + 0.5;
- }
- else {
- /* Bias a little bit for the case where p is a unit length vector,
- * to get exactly zero instead of a small random value depending
- * on float precision. */
- float r = max(0.999999 - sqrt(x * x + y * y + z * z), 0.0);
- if (gradient_type == 5) { /* quadratic sphere */
- return r * r;
- }
- else if (gradient_type == 6) { /* sphere */
- return r;
- }
- }
- return 0.0;
-}
-
-void node_tex_gradient(vec3 co, float gradient_type, out vec4 color, out float fac)
-{
- float f = calc_gradient(co, int(gradient_type));
- f = clamp(f, 0.0, 1.0);
-
- color = vec4(f, f, f, 1.0);
- fac = f;
-}
-
-void node_tex_checker(
- vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac)
-{
- vec3 p = co * scale;
-
- /* Prevent precision issues on unit coordinates. */
- p = (p + 0.000001) * 0.999999;
-
- int xi = int(abs(floor(p.x)));
- int yi = int(abs(floor(p.y)));
- int zi = int(abs(floor(p.z)));
-
- bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2)));
-
- color = check ? color1 : color2;
- fac = check ? 1.0 : 0.0;
-}
-
-vec2 calc_brick_texture(vec3 p,
- float mortar_size,
- float mortar_smooth,
- float bias,
- float brick_width,
- float row_height,
- float offset_amount,
- int offset_frequency,
- float squash_amount,
- int squash_frequency)
-{
- int bricknum, rownum;
- float offset = 0.0;
- float x, y;
-
- rownum = floor_to_int(p.y / row_height);
-
- if (offset_frequency != 0 && squash_frequency != 0) {
- brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */
- offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */
- }
-
- bricknum = floor_to_int((p.x + offset) / brick_width);
-
- x = (p.x + offset) - brick_width * bricknum;
- y = p.y - row_height * rownum;
-
- float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0);
-
- float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
- if (min_dist >= mortar_size) {
- return vec2(tint, 0.0);
- }
- else if (mortar_smooth == 0.0) {
- return vec2(tint, 1.0);
- }
- else {
- min_dist = 1.0 - min_dist / mortar_size;
- return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist));
- }
-}
-
-void node_tex_brick(vec3 co,
- vec4 color1,
- vec4 color2,
- vec4 mortar,
- float scale,
- float mortar_size,
- float mortar_smooth,
- float bias,
- float brick_width,
- float row_height,
- float offset_amount,
- float offset_frequency,
- float squash_amount,
- float squash_frequency,
- out vec4 color,
- out float fac)
-{
- vec2 f2 = calc_brick_texture(co * scale,
- mortar_size,
- mortar_smooth,
- bias,
- brick_width,
- row_height,
- offset_amount,
- int(offset_frequency),
- squash_amount,
- int(squash_frequency));
- float tint = f2.x;
- float f = f2.y;
- if (f != 1.0) {
- float facm = 1.0 - tint;
- color1 = facm * color1 + tint * color2;
- }
- color = mix(color1, mortar, f);
- fac = f;
-}
-
-void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac)
-{
- color = vec4(1.0);
- fac = 1.0;
-}
-
-void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv)
-{
- vec3 nco = normalize(co);
- uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5;
- uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5;
-
- /* Fix pole bleeding */
- float half_height = clamp_size / float(textureSize(ima, 0).y);
- uv.y = clamp(uv.y, half_height, 1.0 - half_height);
- uv.z = 0.0;
-}
-
-void node_tex_environment_mirror_ball(vec3 co, out vec3 uv)
-{
- vec3 nco = normalize(co);
- nco.y -= 1.0;
-
- float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0));
- nco /= max(1e-8, div);
-
- uv = 0.5 * nco.xzz + 0.5;
-}
-
-void node_tex_environment_empty(vec3 co, out vec4 color)
-{
- color = vec4(1.0, 0.0, 1.0, 1.0);
-}
-
-/* 16bits floats limits. Higher/Lower values produce +/-inf. */
-#define safe_color(a) (clamp(a, -65520.0, 65520.0))
-
-void tex_color_alpha_clear(vec4 color, out vec4 result)
-{
- result = vec4(color.rgb, 1.0);
-}
-
-void tex_color_alpha_premultiply(vec4 color, out vec4 result)
-{
- result = vec4(color.rgb * color.a, 1.0);
-}
-
-void tex_color_alpha_unpremultiply(vec4 color, out vec4 result)
-{
- if (color.a == 0.0 || color.a == 1.0) {
- result = vec4(color.rgb, 1.0);
- }
- else {
- result = vec4(color.rgb / color.a, 1.0);
- }
-}
-
-void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- color = safe_color(texture(ima, co.xy));
- alpha = color.a;
-}
-
-void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- color = safe_color(textureLod(ima, co.xy, 0.0));
- 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 = safe_color(texelFetch(ima, pix, 0));
- alpha = color.a;
-}
-
-/* @arg f: signed distance to texel center. */
-void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3)
-{
- vec2 f2 = f * f;
- vec2 f3 = f2 * f;
- /* Bspline coefs (optimized) */
- w3 = f3 / 6.0;
- w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0;
- w1 = f3 * 0.5 - f2 * 1.0 + 2.0 / 3.0;
- w2 = 1.0 - w0 - w1 - w3;
-}
-
-void node_tex_image_cubic_ex(
- vec3 co, sampler2D ima, float do_extend, 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 w0, w1, w2, w3;
- cubic_bspline_coefs(co.xy - tc, w0, w1, w2, 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;
-
- if (do_extend == 1.0) {
- final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5);
- }
- final_co /= tex_size.xyxy;
-
- color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y;
- color += safe_color(textureLod(ima, final_co.zy, 0.0)) * s1.x * s0.y;
- color += safe_color(textureLod(ima, final_co.xw, 0.0)) * s0.x * s1.y;
- color += safe_color(textureLod(ima, final_co.zw, 0.0)) * 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_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- node_tex_image_cubic_ex(co, ima, 0.0, color, alpha);
-}
-
-void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- node_tex_image_cubic_ex(co, ima, 1.0, color, alpha);
-}
-
-void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- /* use cubic for now */
- node_tex_image_cubic_ex(co, ima, 0.0, 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_ex(uv.xyy, ima, 0.0, color1, alpha);
- /* Y projection */
- uv = texco.xz;
- if (N.y > 0.0) {
- uv.x = 1.0 - uv.x;
- }
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha);
- /* Z projection */
- uv = texco.yx;
- if (N.z > 0.0) {
- uv.x = 1.0 - uv.x;
- }
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, 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)
-{
- /* project from direction vector to barycentric coordinates in triangles */
- 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,
- * in between we blend between two textures, and in the middle we a blend
- * between three textures.
- *
- * 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
- * EDIT: Now there is only 4 if's. */
-
- float limit = 0.5 + 0.5 * blend;
-
- vec3 weight;
- weight = N.xyz / (N.xyx + N.yzz);
- weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 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.x < (1.0 - limit) * (N.y + N.z)) {
- weight.x = 0.0;
- weight.z = 1.0 - weight.y;
- }
- else if (N.y < (1.0 - limit) * (N.x + N.z)) {
- weight.y = 0.0;
- weight.x = 1.0 - weight.z;
- }
- else {
- /* last case, we have a mix between three */
- weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, blend);
- }
-
- color = weight.x * color1 + weight.y * color2 + weight.z * color3;
- alpha = color.a;
-}
-
-void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec2 tex_size = vec2(textureSize(ima, 0).xy);
- vec2 minco = min(co.xy, 1.0 - co.xy);
- minco = clamp(minco * tex_size + 0.5, 0.0, 1.0);
- float fac = minco.x * minco.y;
-
- color = mix(vec4(0.0), icolor, fac);
- alpha = color.a;
-}
-
-void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec4 minco = vec4(co.xy, 1.0 - co.xy);
- color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor;
- alpha = color.a;
-}
-
-void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, 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 w0, w1, w2, w3;
- cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3);
-
- /* TODO Optimize this part. I'm sure there is a smarter way to do that.
- * Could do that when sampling? */
-#define CLIP_CUBIC_SAMPLE(samp, size) \
- (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size))))
- ivec2 itex_size = textureSize(ima, 0).xy;
- float fac;
- fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y;
-#undef CLIP_CUBIC_SAMPLE
-
- color = mix(vec4(0.0), icolor, fac);
- alpha = color.a;
-}
-
-void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- tex_clip_cubic(co, ima, icolor, color, alpha);
-}
-
-void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
-{
- color = vec4(0.0);
- alpha = 0.0;
-}
-
-void node_tex_magic(
- vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac)
-{
- vec3 p = co * scale;
- float x = sin((p.x + p.y + p.z) * 5.0);
- float y = cos((-p.x + p.y - p.z) * 5.0);
- float z = -cos((-p.x - p.y + p.z) * 5.0);
-
- if (depth > 0) {
- x *= distortion;
- y *= distortion;
- z *= distortion;
- y = -cos(x - y + z);
- y *= distortion;
- if (depth > 1) {
- x = cos(x - y - z);
- x *= distortion;
- if (depth > 2) {
- z = sin(-x - y - z);
- z *= distortion;
- if (depth > 3) {
- x = -cos(-x + y - z);
- x *= distortion;
- if (depth > 4) {
- y = -sin(-x + y + z);
- y *= distortion;
- if (depth > 5) {
- y = -cos(-x + y + z);
- y *= distortion;
- if (depth > 6) {
- x = cos(x + y + z);
- x *= distortion;
- if (depth > 7) {
- z = sin(x + y - z);
- z *= distortion;
- if (depth > 8) {
- x = -cos(-x - y + z);
- x *= distortion;
- if (depth > 9) {
- y = -sin(x - y + z);
- y *= distortion;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- if (distortion != 0.0) {
- distortion *= 2.0;
- x /= distortion;
- y /= distortion;
- z /= distortion;
- }
-
- color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0);
- fac = (color.x + color.y + color.z) / 3.0;
-}
-
-float noise_fade(float t)
-{
- return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
-}
-
-float noise_scale3(float result)
-{
- return 0.9820 * result;
-}
-
-float noise_nerp(float t, float a, float b)
-{
- return (1.0 - t) * a + t * b;
-}
-
-float noise_grad(uint hash, float x, float y, float z)
-{
- uint h = hash & 15u;
- float u = h < 8u ? x : y;
- float vt = ((h == 12u) || (h == 14u)) ? x : z;
- float v = h < 4u ? y : vt;
- return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v);
-}
-
-float noise_perlin(float x, float y, float z)
-{
- int X;
- float fx = floorfrac(x, X);
- int Y;
- float fy = floorfrac(y, Y);
- int Z;
- float fz = floorfrac(z, Z);
-
- float u = noise_fade(fx);
- float v = noise_fade(fy);
- float w = noise_fade(fz);
-
- float noise_u[2], noise_v[2];
-
- noise_u[0] = noise_nerp(
- u, noise_grad(hash(X, Y, Z), fx, fy, fz), noise_grad(hash(X + 1, Y, Z), fx - 1.0, fy, fz));
-
- noise_u[1] = noise_nerp(u,
- noise_grad(hash(X, Y + 1, Z), fx, fy - 1.0, fz),
- noise_grad(hash(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz));
-
- noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]);
-
- noise_u[0] = noise_nerp(u,
- noise_grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0),
- noise_grad(hash(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0));
-
- noise_u[1] = noise_nerp(u,
- noise_grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0),
- noise_grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0));
-
- noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]);
-
- float r = noise_scale3(noise_nerp(w, noise_v[0], noise_v[1]));
-
- return (isinf(r)) ? 0.0 : r;
-}
-
-float noise(vec3 p)
-{
- return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5;
-}
-
-float snoise(vec3 p)
-{
- return noise_perlin(p.x, p.y, p.z);
-}
-
-float noise_turbulence(vec3 p, float octaves, int hard)
-{
- float fscale = 1.0;
- float amp = 1.0;
- float sum = 0.0;
- octaves = clamp(octaves, 0.0, 16.0);
- int n = int(octaves);
- for (int i = 0; i <= n; i++) {
- float t = noise(fscale * p);
- if (hard != 0) {
- t = abs(2.0 * t - 1.0);
- }
- sum += t * amp;
- amp *= 0.5;
- fscale *= 2.0;
- }
- float rmd = octaves - floor(octaves);
- if (rmd != 0.0) {
- float t = noise(fscale * p);
- if (hard != 0) {
- t = abs(2.0 * t - 1.0);
- }
- float sum2 = sum + t * amp;
- sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
- sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
- return (1.0 - rmd) * sum + rmd * sum2;
- }
- else {
- sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
- return sum;
- }
-}
-
-void node_tex_noise(
- vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac)
-{
- vec3 p = co * scale;
- int hard = 0;
- if (distortion != 0.0) {
- vec3 r, offset = vec3(13.5, 13.5, 13.5);
- r.x = noise(p + offset) * distortion;
- r.y = noise(p) * distortion;
- r.z = noise(p - offset) * distortion;
- p += r;
- }
-
- fac = noise_turbulence(p, detail, hard);
- color = vec4(fac,
- noise_turbulence(vec3(p.y, p.x, p.z), detail, hard),
- noise_turbulence(vec3(p.y, p.z, p.x), detail, hard),
- 1);
-}
-
-/* Musgrave fBm
- *
- * H: fractal increment parameter
- * lacunarity: gap between successive frequencies
- * octaves: number of frequencies in the fBm
- *
- * from "Texturing and Modelling: A procedural approach"
- */
-
-float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves)
-{
- float rmd;
- float value = 0.0;
- float pwr = 1.0;
- float pwHL = pow(lacunarity, -H);
-
- for (int i = 0; i < int(octaves); i++) {
- value += snoise(p) * pwr;
- pwr *= pwHL;
- p *= lacunarity;
- }
-
- rmd = octaves - floor(octaves);
- if (rmd != 0.0) {
- value += rmd * snoise(p) * pwr;
- }
-
- return value;
-}
-
-/* Musgrave Multifractal
- *
- * H: highest fractal dimension
- * lacunarity: gap between successive frequencies
- * octaves: number of frequencies in the fBm
- */
-
-float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves)
-{
- float rmd;
- float value = 1.0;
- float pwr = 1.0;
- float pwHL = pow(lacunarity, -H);
-
- for (int i = 0; i < int(octaves); i++) {
- value *= (pwr * snoise(p) + 1.0);
- pwr *= pwHL;
- p *= lacunarity;
- }
-
- rmd = octaves - floor(octaves);
- if (rmd != 0.0) {
- value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
- }
-
- return value;
-}
-
-/* Musgrave Heterogeneous Terrain
- *
- * H: fractal dimension of the roughest area
- * lacunarity: gap between successive frequencies
- * octaves: number of frequencies in the fBm
- * offset: raises the terrain from `sea level'
- */
-
-float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset)
-{
- float value, increment, rmd;
- float pwHL = pow(lacunarity, -H);
- float pwr = pwHL;
-
- /* first unscaled octave of function; later octaves are scaled */
- value = offset + snoise(p);
- p *= lacunarity;
-
- for (int i = 1; i < int(octaves); i++) {
- increment = (snoise(p) + offset) * pwr * value;
- value += increment;
- pwr *= pwHL;
- p *= lacunarity;
- }
-
- rmd = octaves - floor(octaves);
- if (rmd != 0.0) {
- increment = (snoise(p) + offset) * pwr * value;
- value += rmd * increment;
- }
-
- return value;
-}
-
-/* Hybrid Additive/Multiplicative Multifractal Terrain
- *
- * H: fractal dimension of the roughest area
- * lacunarity: gap between successive frequencies
- * octaves: number of frequencies in the fBm
- * offset: raises the terrain from `sea level'
- */
-
-float noise_musgrave_hybrid_multi_fractal(
- vec3 p, float H, float lacunarity, float octaves, float offset, float gain)
-{
- float result, signal, weight, rmd;
- float pwHL = pow(lacunarity, -H);
- float pwr = pwHL;
-
- result = snoise(p) + offset;
- weight = gain * result;
- p *= lacunarity;
-
- for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
- if (weight > 1.0) {
- weight = 1.0;
- }
-
- signal = (snoise(p) + offset) * pwr;
- pwr *= pwHL;
- result += weight * signal;
- weight *= gain * signal;
- p *= lacunarity;
- }
-
- rmd = octaves - floor(octaves);
- if (rmd != 0.0) {
- result += rmd * ((snoise(p) + offset) * pwr);
- }
-
- return result;
-}
-
-/* Ridged Multifractal Terrain
- *
- * H: fractal dimension of the roughest area
- * lacunarity: gap between successive frequencies
- * octaves: number of frequencies in the fBm
- * offset: raises the terrain from `sea level'
- */
-
-float noise_musgrave_ridged_multi_fractal(
- vec3 p, float H, float lacunarity, float octaves, float offset, float gain)
-{
- float result, signal, weight;
- float pwHL = pow(lacunarity, -H);
- float pwr = pwHL;
-
- signal = offset - abs(snoise(p));
- signal *= signal;
- result = signal;
- weight = 1.0;
-
- for (int i = 1; i < int(octaves); i++) {
- p *= lacunarity;
- weight = clamp(signal * gain, 0.0, 1.0);
- signal = offset - abs(snoise(p));
- signal *= signal;
- signal *= weight;
- result += signal * pwr;
- pwr *= pwHL;
- }
-
- return result;
-}
-
-float svm_musgrave(int type,
- float dimension,
- float lacunarity,
- float octaves,
- float offset,
- float intensity,
- float gain,
- vec3 p)
-{
- if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) {
- return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
- }
- else if (type == 1 /* NODE_MUSGRAVE_FBM */) {
- return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
- }
- else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) {
- return intensity *
- noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
- }
- else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) {
- return intensity *
- noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
- }
- else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) {
- return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
- }
- return 0.0;
-}
-
-void node_tex_musgrave(vec3 co,
- float scale,
- float detail,
- float dimension,
- float lacunarity,
- float offset,
- float gain,
- float type,
- out vec4 color,
- out float fac)
-{
- fac = svm_musgrave(int(type), dimension, lacunarity, detail, offset, 1.0, gain, co *scale);
-
- color = vec4(fac, fac, fac, 1.0);
-}
-
-void node_tex_sky(vec3 co, out vec4 color)
-{
- color = vec4(1.0);
-}
-
-void node_tex_voronoi(vec3 co,
- float scale,
- float exponent,
- float coloring,
- float metric,
- float feature,
- out vec4 color,
- out float fac)
-{
- vec3 p = co * scale;
- int xx, yy, zz, xi, yi, zi;
- vec4 da = vec4(1e10);
- vec3 pa[4] = vec3[4](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
-
- xi = floor_to_int(p[0]);
- yi = floor_to_int(p[1]);
- zi = floor_to_int(p[2]);
-
- for (xx = xi - 1; xx <= xi + 1; xx++) {
- for (yy = yi - 1; yy <= yi + 1; yy++) {
- for (zz = zi - 1; zz <= zi + 1; zz++) {
- vec3 ip = vec3(xx, yy, zz);
- vec3 vp = cellnoise_color(ip);
- vec3 pd = p - (vp + ip);
-
- float d = 0.0;
- if (metric == 0.0) { /* SHD_VORONOI_DISTANCE 0 */
- d = dot(pd, pd);
- }
- else if (metric == 1.0) { /* SHD_VORONOI_MANHATTAN 1 */
- d = abs(pd[0]) + abs(pd[1]) + abs(pd[2]);
- }
- else if (metric == 2.0) { /* SHD_VORONOI_CHEBYCHEV 2 */
- d = max(abs(pd[0]), max(abs(pd[1]), abs(pd[2])));
- }
- else if (metric == 3.0) { /* SHD_VORONOI_MINKOWSKI 3 */
- d = pow(pow(abs(pd[0]), exponent) + pow(abs(pd[1]), exponent) +
- pow(abs(pd[2]), exponent),
- 1.0 / exponent);
- }
-
- vp += vec3(xx, yy, zz);
- if (d < da[0]) {
- da.yzw = da.xyz;
- da[0] = d;
-
- pa[3] = pa[2];
- pa[2] = pa[1];
- pa[1] = pa[0];
- pa[0] = vp;
- }
- else if (d < da[1]) {
- da.zw = da.yz;
- da[1] = d;
-
- pa[3] = pa[2];
- pa[2] = pa[1];
- pa[1] = vp;
- }
- else if (d < da[2]) {
- da[3] = da[2];
- da[2] = d;
-
- pa[3] = pa[2];
- pa[2] = vp;
- }
- else if (d < da[3]) {
- da[3] = d;
- pa[3] = vp;
- }
- }
- }
- }
-
- if (coloring == 0.0) {
- /* Intensity output */
- if (feature == 0.0) { /* F1 */
- fac = abs(da[0]);
- }
- else if (feature == 1.0) { /* F2 */
- fac = abs(da[1]);
- }
- else if (feature == 2.0) { /* F3 */
- fac = abs(da[2]);
- }
- else if (feature == 3.0) { /* F4 */
- fac = abs(da[3]);
- }
- else if (feature == 4.0) { /* F2F1 */
- fac = abs(da[1] - da[0]);
- }
- color = vec4(fac, fac, fac, 1.0);
- }
- else {
- /* Color output */
- vec3 col = vec3(fac, fac, fac);
- if (feature == 0.0) { /* F1 */
- col = pa[0];
- }
- else if (feature == 1.0) { /* F2 */
- col = pa[1];
- }
- else if (feature == 2.0) { /* F3 */
- col = pa[2];
- }
- else if (feature == 3.0) { /* F4 */
- col = pa[3];
- }
- else if (feature == 4.0) { /* F2F1 */
- col = abs(pa[1] - pa[0]);
- }
-
- color = vec4(cellnoise_color(col), 1.0);
- fac = (color.x + color.y + color.z) * (1.0 / 3.0);
- }
-}
-
-float calc_wave(
- vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile)
-{
- float n;
-
- if (wave_type == 0) { /* type bands */
- n = (p.x + p.y + p.z) * 10.0;
- }
- else { /* type rings */
- n = length(p) * 20.0;
- }
-
- if (distortion != 0.0) {
- n += distortion * noise_turbulence(p * detail_scale, detail, 0);
- }
-
- if (wave_profile == 0) { /* profile sin */
- return 0.5 + 0.5 * sin(n);
- }
- else { /* profile saw */
- n /= 2.0 * M_PI;
- n -= int(n);
- return (n < 0.0) ? n + 1.0 : n;
- }
-}
-
-void node_tex_wave(vec3 co,
- float scale,
- float distortion,
- float detail,
- float detail_scale,
- float wave_type,
- float wave_profile,
- out vec4 color,
- out float fac)
-{
- float f;
- f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile));
-
- color = vec4(f, f, f, 1.0);
- fac = f;
-}
-
-/* light path */
-
-void node_light_path(out float is_camera_ray,
- out float is_shadow_ray,
- out float is_diffuse_ray,
- out float is_glossy_ray,
- out float is_singular_ray,
- out float is_reflection_ray,
- out float is_transmission_ray,
- out float ray_length,
- out float ray_depth,
- out float diffuse_depth,
- out float glossy_depth,
- out float transparent_depth,
- out float transmission_depth)
-{
- /* Supported. */
- is_camera_ray = (rayType == EEVEE_RAY_CAMERA) ? 1.0 : 0.0;
- is_shadow_ray = (rayType == EEVEE_RAY_SHADOW) ? 1.0 : 0.0;
- is_diffuse_ray = (rayType == EEVEE_RAY_DIFFUSE) ? 1.0 : 0.0;
- is_glossy_ray = (rayType == EEVEE_RAY_GLOSSY) ? 1.0 : 0.0;
- /* Kind of supported. */
- is_singular_ray = is_glossy_ray;
- is_reflection_ray = is_glossy_ray;
- is_transmission_ray = is_glossy_ray;
- ray_depth = rayDepth;
- diffuse_depth = (is_diffuse_ray == 1.0) ? rayDepth : 0.0;
- glossy_depth = (is_glossy_ray == 1.0) ? rayDepth : 0.0;
- transmission_depth = (is_transmission_ray == 1.0) ? glossy_depth : 0.0;
- /* Not supported. */
- ray_length = 1.0;
- transparent_depth = 0.0;
-}
-
-void node_light_falloff(
- float strength, float tsmooth, out float quadratic, out float linear, out float constant)
-{
- quadratic = strength;
- linear = strength;
- constant = strength;
-}
-
-void node_object_info(mat4 obmat,
- vec4 info,
- float mat_index,
- out vec3 location,
- out float object_index,
- out float material_index,
- out float random)
-{
- location = obmat[3].xyz;
- object_index = info.x;
- material_index = mat_index;
- random = info.z;
-}
-
-void node_normal_map(vec4 info, vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal)
-{
- if (all(equal(tangent, vec4(0.0, 0.0, 0.0, 1.0)))) {
- outnormal = normal;
- return;
- }
- tangent *= (gl_FrontFacing ? 1.0 : -1.0);
- vec3 B = tangent.w * cross(normal, tangent.xyz) * info.w;
-
- outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal;
- outnormal = normalize(outnormal);
-}
-
-void node_bump(
- float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result)
-{
- N = mat3(ViewMatrix) * normalize(N);
- dist *= gl_FrontFacing ? invert : -invert;
-
- vec3 dPdx = dFdx(surf_pos);
- vec3 dPdy = dFdy(surf_pos);
-
- /* Get surface tangents from normal. */
- vec3 Rx = cross(dPdy, N);
- vec3 Ry = cross(N, dPdx);
-
- /* Compute surface gradient and determinant. */
- float det = dot(dPdx, Rx);
-
- float dHdx = dFdx(height);
- float dHdy = dFdy(height);
- vec3 surfgrad = dHdx * Rx + dHdy * Ry;
-
- strength = max(strength, 0.0);
-
- result = normalize(abs(det) * N - dist * sign(det) * surfgrad);
- result = normalize(mix(N, result, strength));
-
- result = mat3(ViewMatrixInverse) * result;
-}
-
-void node_bevel(float radius, vec3 N, out vec3 result)
-{
- result = N;
-}
-
-void node_hair_info(out float is_strand,
- out float intercept,
- out float thickness,
- out vec3 tangent,
- out float random)
-{
-#ifdef HAIR_SHADER
- is_strand = 1.0;
- intercept = hairTime;
- thickness = hairThickness;
- tangent = normalize(worldNormal);
- random = wang_hash_noise(
- uint(hairStrandID)); /* TODO: could be precomputed per strand instead. */
-#else
- is_strand = 0.0;
- intercept = 0.0;
- thickness = 0.0;
- tangent = vec3(1.0);
- random = 0.0;
-#endif
-}
-
-void node_displacement_object(
- float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result)
-{
- N = (vec4(N, 0.0) * obmat).xyz;
- result = (height - midlevel) * scale * normalize(N);
- result = (obmat * vec4(result, 0.0)).xyz;
-}
-
-void node_displacement_world(float height, float midlevel, float scale, vec3 N, out vec3 result)
-{
- result = (height - midlevel) * scale * normalize(N);
-}
-
-void node_vector_displacement_tangent(vec4 vector,
- float midlevel,
- float scale,
- vec4 tangent,
- vec3 normal,
- mat4 obmat,
- mat4 viewmat,
- out vec3 result)
-{
- /* TODO(fclem) this is broken. revisit latter. */
- vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz);
- vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz);
- vec3 B_object = tangent.w * normalize(cross(N_object, T_object));
-
- vec3 offset = (vector.xyz - vec3(midlevel)) * scale;
- result = offset.x * T_object + offset.y * N_object + offset.z * B_object;
- result = (obmat * vec4(result, 0.0)).xyz;
-}
-
-void node_vector_displacement_object(
- vec4 vector, float midlevel, float scale, mat4 obmat, out vec3 result)
-{
- result = (vector.xyz - vec3(midlevel)) * scale;
- result = (obmat * vec4(result, 0.0)).xyz;
-}
-
-void node_vector_displacement_world(vec4 vector, float midlevel, float scale, out vec3 result)
-{
- result = (vector.xyz - vec3(midlevel)) * scale;
-}
-
-/* output */
-
-void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result)
-{
-#ifdef VOLUMETRICS
- result = volume;
-#else
- result = surface;
-#endif
-}
-
-uniform float backgroundAlpha;
-
-void node_output_world(Closure surface, Closure volume, out Closure result)
-{
-#ifndef VOLUMETRICS
- result.radiance = surface.radiance * backgroundAlpha;
- result.transmittance = vec3(1.0 - backgroundAlpha);
-#else
- result = volume;
-#endif /* VOLUMETRICS */
-}
-
-/* TODO : clean this ifdef mess */
-/* EEVEE output */
-void world_normals_get(out vec3 N)
-{
-#ifndef VOLUMETRICS
-# ifdef HAIR_SHADER
- vec3 B = normalize(cross(worldNormal, hairTangent));
- float cos_theta;
- if (hairThicknessRes == 1) {
- vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
- /* Random cosine normal distribution on the hair surface. */
- cos_theta = rand.x * 2.0 - 1.0;
- }
- else {
- /* Shade as a cylinder. */
- cos_theta = hairThickTime / hairThickness;
- }
- float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));
- N = normalize(worldNormal * sin_theta + B * cos_theta);
-# else
- N = gl_FrontFacing ? worldNormal : -worldNormal;
-# endif
-#else
- generated_from_orco(vec3(0.0), N);
-#endif
-}
-
-#ifndef VOLUMETRICS
-void node_eevee_specular(vec4 diffuse,
- vec4 specular,
- float roughness,
- vec4 emissive,
- float transp,
- vec3 normal,
- float clearcoat,
- float clearcoat_roughness,
- vec3 clearcoat_normal,
- float occlusion,
- float ssr_id,
- out Closure result)
-{
- normal = normalize(normal);
-
- vec3 out_diff, out_spec, ssr_spec;
- eevee_closure_default_clearcoat(normal,
- diffuse.rgb,
- specular.rgb,
- vec3(1.0),
- int(ssr_id),
- roughness,
- clearcoat_normal,
- clearcoat * 0.25,
- clearcoat_roughness,
- occlusion,
- out_diff,
- out_spec,
- ssr_spec);
-
- float alpha = 1.0 - transp;
- result = CLOSURE_DEFAULT;
- result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb;
- result.radiance *= alpha;
- result.transmittance = vec3(transp);
-
- closure_load_ssr_data(ssr_spec * alpha, roughness, normal, viewCameraVec, int(ssr_id), result);
-}
-
-void node_shader_to_rgba(Closure cl, out vec4 outcol, out float outalpha)
-{
- vec4 spec_accum = vec4(0.0);
- if (ssrToggle && FLAG_TEST(cl.flag, CLOSURE_SSR_FLAG)) {
- vec3 V = cameraVec;
- vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec);
- vec3 N = transform_direction(ViewMatrixInverse, vN);
- float roughness = cl.ssr_data.a;
- float roughnessSquared = max(1e-3, roughness * roughness);
- fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum);
- }
-
- outalpha = avg(cl.transmittance);
- outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0);
-
-# ifdef USE_SSS
-# ifdef USE_SSS_ALBEDO
- outcol.rgb += cl.sss_data.rgb * cl.sss_albedo;
-# else
- outcol.rgb += cl.sss_data.rgb;
-# endif
-# endif
-}
-
-#endif /* VOLUMETRICS */
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl
new file mode 100644
index 00000000000..99117400c57
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_add_shader.glsl
@@ -0,0 +1,4 @@
+void node_add_shader(Closure shader1, Closure shader2, out Closure shader)
+{
+ shader = closure_add(shader1, shader2);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl
new file mode 100644
index 00000000000..8f8ebebb5f1
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_ambient_occlusion.glsl
@@ -0,0 +1,13 @@
+#ifndef VOLUMETRICS
+void node_ambient_occlusion(
+ vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao)
+{
+ vec3 bent_normal;
+ vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
+ result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal);
+ result_color = result_ao * color;
+}
+#else
+/* Stub ambient occlusion because it is not compatible with volumetrics. */
+# define node_ambient_occlusion
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl
new file mode 100644
index 00000000000..a8a900b40c6
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_anisotropic.glsl
@@ -0,0 +1,15 @@
+#ifndef VOLUMETRICS
+void node_bsdf_anisotropic(vec4 color,
+ float roughness,
+ float anisotropy,
+ float rotation,
+ vec3 N,
+ vec3 T,
+ out Closure result)
+{
+ node_bsdf_glossy(color, roughness, N, -1, result);
+}
+#else
+/* Stub anisotropic because it is not compatible with volumetrics. */
+# define node_bsdf_anisotropic
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl
new file mode 100644
index 00000000000..10e1b4563bc
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_attribute.glsl
@@ -0,0 +1,6 @@
+void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf)
+{
+ outcol = vec4(attr, 1.0);
+ outvec = attr;
+ outf = avg(attr);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_background.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_background.glsl
new file mode 100644
index 00000000000..69ef4dcb7c7
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_background.glsl
@@ -0,0 +1,11 @@
+void node_background(vec4 color, float strength, out Closure result)
+{
+#ifndef VOLUMETRICS
+ color *= strength;
+ result = CLOSURE_DEFAULT;
+ result.radiance = color.rgb;
+ result.transmittance = vec3(0.0);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_bevel.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_bevel.glsl
new file mode 100644
index 00000000000..0d99390c2f9
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_bevel.glsl
@@ -0,0 +1,4 @@
+void node_bevel(float radius, vec3 N, out vec3 result)
+{
+ result = N;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_blackbody.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_blackbody.glsl
new file mode 100644
index 00000000000..d0111aa3839
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_blackbody.glsl
@@ -0,0 +1,13 @@
+void node_blackbody(float temperature, sampler1DArray spectrummap, float layer, out vec4 color)
+{
+ if (temperature >= 12000.0) {
+ color = vec4(0.826270103, 0.994478524, 1.56626022, 1.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, layer)).rgb, 1.0);
+ }
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_bright_contrast.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_bright_contrast.glsl
new file mode 100644
index 00000000000..a5a10833065
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_bright_contrast.glsl
@@ -0,0 +1,10 @@
+void brightness_contrast(vec4 col, float brightness, float contrast, out vec4 outcol)
+{
+ float a = 1.0 + contrast;
+ float b = brightness - contrast * 0.5;
+
+ outcol.r = max(a * col.r + b, 0.0);
+ outcol.g = max(a * col.g + b, 0.0);
+ outcol.b = max(a * col.b + b, 0.0);
+ outcol.a = col.a;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl
new file mode 100644
index 00000000000..1137e5acdc6
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_bump.glsl
@@ -0,0 +1,27 @@
+void node_bump(
+ float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result)
+{
+ N = mat3(ViewMatrix) * normalize(N);
+ dist *= gl_FrontFacing ? invert : -invert;
+
+ vec3 dPdx = dFdx(surf_pos);
+ vec3 dPdy = dFdy(surf_pos);
+
+ /* Get surface tangents from normal. */
+ vec3 Rx = cross(dPdy, N);
+ vec3 Ry = cross(N, dPdx);
+
+ /* Compute surface gradient and determinant. */
+ float det = dot(dPdx, Rx);
+
+ float dHdx = dFdx(height);
+ float dHdy = dFdy(height);
+ vec3 surfgrad = dHdx * Rx + dHdy * Ry;
+
+ strength = max(strength, 0.0);
+
+ result = normalize(abs(det) * N - dist * sign(det) * surfgrad);
+ result = normalize(mix(N, result, strength));
+
+ result = mat3(ViewMatrixInverse) * result;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_camera.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_camera.glsl
new file mode 100644
index 00000000000..03e61e9f472
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_camera.glsl
@@ -0,0 +1,6 @@
+void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist)
+{
+ outdepth = abs(co.z);
+ outdist = length(co);
+ outview = normalize(co);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_cell_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_cell_noise.glsl
new file mode 100644
index 00000000000..881f2386cd4
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_cell_noise.glsl
@@ -0,0 +1,17 @@
+float cellnoise(vec3 p)
+{
+ int ix = quick_floor(p.x);
+ int iy = quick_floor(p.y);
+ int iz = quick_floor(p.z);
+
+ return hash_uint3_to_float(uint(ix), uint(iy), uint(iz));
+}
+
+vec3 cellnoise_color(vec3 p)
+{
+ float r = cellnoise(p.xyz);
+ float g = cellnoise(p.yxz);
+ float b = cellnoise(p.yzx);
+
+ return vec3(r, g, b);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl
new file mode 100644
index 00000000000..b8842064b6f
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_clamp.glsl
@@ -0,0 +1,4 @@
+void clamp_value(float value, float min, float max, out float result)
+{
+ result = clamp(value, min, max);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_color_ramp.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_color_ramp.glsl
new file mode 100644
index 00000000000..9fe45f91f45
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_color_ramp.glsl
@@ -0,0 +1,28 @@
+void valtorgb_opti_constant(
+ float fac, float edge, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha)
+{
+ outcol = (fac > edge) ? color2 : color1;
+ outalpha = outcol.a;
+}
+
+void valtorgb_opti_linear(
+ float fac, vec2 mulbias, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha)
+{
+ fac = clamp(fac * mulbias.x + mulbias.y, 0.0, 1.0);
+ outcol = mix(color1, color2, fac);
+ outalpha = outcol.a;
+}
+
+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)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ outcol = texelFetch(colormap, ivec2(fac * (textureSize(colormap, 0).x - 1), layer), 0);
+ outalpha = outcol.a;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl
new file mode 100644
index 00000000000..a5c3a990d90
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_color_util.glsl
@@ -0,0 +1,111 @@
+void rgb_to_hsv(vec4 rgb, out vec4 outcol)
+{
+ float cmax, cmin, h, s, v, cdelta;
+ vec3 c;
+
+ cmax = max(rgb[0], max(rgb[1], rgb[2]));
+ cmin = min(rgb[0], min(rgb[1], rgb[2]));
+ cdelta = cmax - cmin;
+
+ v = cmax;
+ if (cmax != 0.0) {
+ s = cdelta / cmax;
+ }
+ else {
+ s = 0.0;
+ h = 0.0;
+ }
+
+ if (s == 0.0) {
+ h = 0.0;
+ }
+ else {
+ c = (vec3(cmax) - rgb.xyz) / cdelta;
+
+ if (rgb.x == cmax) {
+ h = c[2] - c[1];
+ }
+ else if (rgb.y == cmax) {
+ h = 2.0 + c[0] - c[2];
+ }
+ else {
+ h = 4.0 + c[1] - c[0];
+ }
+
+ h /= 6.0;
+
+ if (h < 0.0) {
+ h += 1.0;
+ }
+ }
+
+ outcol = vec4(h, s, v, rgb.w);
+}
+
+void hsv_to_rgb(vec4 hsv, out vec4 outcol)
+{
+ float i, f, p, q, t, h, s, v;
+ vec3 rgb;
+
+ h = hsv[0];
+ s = hsv[1];
+ v = hsv[2];
+
+ if (s == 0.0) {
+ rgb = vec3(v, v, v);
+ }
+ else {
+ if (h == 1.0) {
+ h = 0.0;
+ }
+
+ h *= 6.0;
+ i = floor(h);
+ f = h - i;
+ rgb = vec3(f, f, f);
+ p = v * (1.0 - s);
+ q = v * (1.0 - (s * f));
+ t = v * (1.0 - (s * (1.0 - f)));
+
+ if (i == 0.0) {
+ rgb = vec3(v, t, p);
+ }
+ else if (i == 1.0) {
+ rgb = vec3(q, v, p);
+ }
+ else if (i == 2.0) {
+ rgb = vec3(p, v, t);
+ }
+ else if (i == 3.0) {
+ rgb = vec3(p, q, v);
+ }
+ else if (i == 4.0) {
+ rgb = vec3(t, p, v);
+ }
+ else {
+ rgb = vec3(v, p, q);
+ }
+ }
+
+ outcol = vec4(rgb, hsv.w);
+}
+
+void color_alpha_clear(vec4 color, out vec4 result)
+{
+ result = vec4(color.rgb, 1.0);
+}
+
+void color_alpha_premultiply(vec4 color, out vec4 result)
+{
+ result = vec4(color.rgb * color.a, 1.0);
+}
+
+void color_alpha_unpremultiply(vec4 color, out vec4 result)
+{
+ if (color.a == 0.0 || color.a == 1.0) {
+ result = vec4(color.rgb, 1.0);
+ }
+ else {
+ result = vec4(color.rgb / color.a, 1.0);
+ }
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_combine_hsv.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_combine_hsv.glsl
new file mode 100644
index 00000000000..2ce061da3cb
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_combine_hsv.glsl
@@ -0,0 +1,4 @@
+void combine_hsv(float h, float s, float v, out vec4 col)
+{
+ hsv_to_rgb(vec4(h, s, v, 1.0), col);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_combine_rgb.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_combine_rgb.glsl
new file mode 100644
index 00000000000..d9c882a048f
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_combine_rgb.glsl
@@ -0,0 +1,4 @@
+void combine_rgb(float r, float g, float b, out vec4 col)
+{
+ col = vec4(r, g, b, 1.0);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_combine_xyz.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_combine_xyz.glsl
new file mode 100644
index 00000000000..d8d132ff1f9
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_combine_xyz.glsl
@@ -0,0 +1,4 @@
+void combine_xyz(float x, float y, float z, out vec3 vec)
+{
+ vec = vec3(x, y, z);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
new file mode 100644
index 00000000000..14acf9925a2
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_diffuse.glsl
@@ -0,0 +1,13 @@
+#ifndef VOLUMETRICS
+void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
+{
+ N = normalize(N);
+ result = CLOSURE_DEFAULT;
+ eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance);
+ closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
+ result.radiance *= color.rgb;
+}
+#else
+/* Stub diffuse because it is not compatible with volumetrics. */
+# define node_bsdf_diffuse
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_displacement.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_displacement.glsl
new file mode 100644
index 00000000000..0838b5c8b71
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_displacement.glsl
@@ -0,0 +1,12 @@
+void node_displacement_object(
+ float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result)
+{
+ N = (vec4(N, 0.0) * obmat).xyz;
+ result = (height - midlevel) * scale * normalize(N);
+ result = (obmat * vec4(result, 0.0)).xyz;
+}
+
+void node_displacement_world(float height, float midlevel, float scale, vec3 N, out vec3 result)
+{
+ result = (height - midlevel) * scale * normalize(N);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
new file mode 100644
index 00000000000..e69a53b6596
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_eevee_specular.glsl
@@ -0,0 +1,40 @@
+#ifndef VOLUMETRICS
+void node_eevee_specular(vec4 diffuse,
+ vec4 specular,
+ float roughness,
+ vec4 emissive,
+ float transp,
+ vec3 normal,
+ float clearcoat,
+ float clearcoat_roughness,
+ vec3 clearcoat_normal,
+ float occlusion,
+ float ssr_id,
+ out Closure result)
+{
+ normal = normalize(normal);
+
+ vec3 out_diff, out_spec, ssr_spec;
+ eevee_closure_default_clearcoat(normal,
+ diffuse.rgb,
+ specular.rgb,
+ vec3(1.0),
+ int(ssr_id),
+ roughness,
+ clearcoat_normal,
+ clearcoat * 0.25,
+ clearcoat_roughness,
+ occlusion,
+ out_diff,
+ out_spec,
+ ssr_spec);
+
+ float alpha = 1.0 - transp;
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb;
+ result.radiance *= alpha;
+ result.transmittance = vec3(transp);
+
+ closure_load_ssr_data(ssr_spec * alpha, roughness, normal, viewCameraVec, int(ssr_id), result);
+}
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl
new file mode 100644
index 00000000000..092b9ed08bb
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_emission.glsl
@@ -0,0 +1,10 @@
+void node_emission(vec4 color, float strength, vec3 vN, out Closure result)
+{
+ result = CLOSURE_DEFAULT;
+#ifndef VOLUMETRICS
+ result.radiance = color.rgb * strength;
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+#else
+ result.emission = color.rgb * strength;
+#endif
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl
new file mode 100644
index 00000000000..2a925c2a622
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_fractal_noise.glsl
@@ -0,0 +1,32 @@
+float noise_turbulence(vec3 p, float octaves, int hard)
+{
+ float fscale = 1.0;
+ float amp = 1.0;
+ float sum = 0.0;
+ octaves = clamp(octaves, 0.0, 16.0);
+ int n = int(octaves);
+ for (int i = 0; i <= n; i++) {
+ float t = noise(fscale * p);
+ if (hard != 0) {
+ t = abs(2.0 * t - 1.0);
+ }
+ sum += t * amp;
+ amp *= 0.5;
+ fscale *= 2.0;
+ }
+ float rmd = octaves - floor(octaves);
+ if (rmd != 0.0) {
+ float t = noise(fscale * p);
+ if (hard != 0) {
+ t = abs(2.0 * t - 1.0);
+ }
+ float sum2 = sum + t * amp;
+ sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
+ sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1));
+ return (1.0 - rmd) * sum + rmd * sum2;
+ }
+ else {
+ sum *= (float(1 << n) / float((1 << (n + 1)) - 1));
+ return sum;
+ }
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_fresnel.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_fresnel.glsl
new file mode 100644
index 00000000000..7a4d28f2dd6
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_fresnel.glsl
@@ -0,0 +1,37 @@
+float fresnel_dielectric_cos(float cosi, float eta)
+{
+ /* compute fresnel reflectance without explicitly computing
+ * the refracted direction */
+ float c = abs(cosi);
+ float g = eta * eta - 1.0 + c * c;
+ float result;
+
+ if (g > 0.0) {
+ g = sqrt(g);
+ float A = (g - c) / (g + c);
+ float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0);
+ result = 0.5 * A * A * (1.0 + B * B);
+ }
+ else {
+ result = 1.0; /* TIR (no refracted component) */
+ }
+
+ return result;
+}
+
+float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta)
+{
+ /* compute fresnel reflectance without explicitly computing
+ * the refracted direction */
+ return fresnel_dielectric_cos(dot(Incoming, Normal), eta);
+}
+
+void node_fresnel(float ior, vec3 N, vec3 I, out float result)
+{
+ N = normalize(N);
+ /* handle perspective/orthographic */
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+
+ float eta = max(ior, 0.00001);
+ result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_gamma.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_gamma.glsl
new file mode 100644
index 00000000000..5733992f8dd
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_gamma.glsl
@@ -0,0 +1,14 @@
+void node_gamma(vec4 col, float gamma, out vec4 outcol)
+{
+ outcol = col;
+
+ if (col.r > 0.0) {
+ outcol.r = compatible_pow(col.r, gamma);
+ }
+ if (col.g > 0.0) {
+ outcol.g = compatible_pow(col.g, gamma);
+ }
+ if (col.b > 0.0) {
+ outcol.b = compatible_pow(col.b, gamma);
+ }
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_geometry.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_geometry.glsl
new file mode 100644
index 00000000000..79614495499
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_geometry.glsl
@@ -0,0 +1,46 @@
+void node_geometry(vec3 I,
+ vec3 N,
+ vec3 orco,
+ mat4 objmat,
+ mat4 toworld,
+ vec2 barycentric,
+ out vec3 position,
+ out vec3 normal,
+ out vec3 tangent,
+ out vec3 true_normal,
+ out vec3 incoming,
+ out vec3 parametric,
+ out float backfacing,
+ out float pointiness)
+{
+ /* handle perspective/orthographic */
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+ incoming = -(toworld * vec4(I_view, 0.0)).xyz;
+
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ position = -incoming;
+ true_normal = normal = incoming;
+ tangent = parametric = vec3(0.0);
+ vec3(0.0);
+ backfacing = 0.0;
+ pointiness = 0.0;
+#else
+
+ position = worldPosition;
+# ifndef VOLUMETRICS
+ normal = normalize(N);
+ vec3 B = dFdx(worldPosition);
+ vec3 T = dFdy(worldPosition);
+ true_normal = normalize(cross(B, T));
+# else
+ normal = (toworld * vec4(N, 0.0)).xyz;
+ true_normal = normal;
+# endif
+ tangent_orco_z(orco, orco);
+ node_tangent(N, orco, objmat, tangent);
+
+ parametric = vec3(barycentric, 0.0);
+ backfacing = (gl_FrontFacing) ? 0.0 : 1.0;
+ pointiness = 0.5;
+#endif
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
new file mode 100644
index 00000000000..8cc8ba2dd15
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_glass.glsl
@@ -0,0 +1,23 @@
+#ifndef VOLUMETRICS
+void node_bsdf_glass(
+ vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result)
+{
+ N = normalize(N);
+ vec3 out_spec, out_refr, ssr_spec;
+ vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb :
+ color.rgb; /* Simulate 2 transmission event */
+ eevee_closure_glass(
+ N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
+ out_refr *= refr_color;
+ out_spec *= color.rgb;
+ float fresnel = F_eta(ior, dot(N, cameraVec));
+ vec3 vN = mat3(ViewMatrix) * N;
+ result = CLOSURE_DEFAULT;
+ result.radiance = mix(out_refr, out_spec, fresnel);
+ closure_load_ssr_data(
+ ssr_spec * color.rgb * fresnel, roughness, N, viewCameraVec, int(ssr_id), result);
+}
+#else
+/* Stub glass because it is not compatible with volumetrics. */
+# define node_bsdf_glass
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
new file mode 100644
index 00000000000..4d582e63725
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_glossy.glsl
@@ -0,0 +1,15 @@
+#ifndef VOLUMETRICS
+void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result)
+{
+ N = normalize(N);
+ vec3 out_spec, ssr_spec;
+ eevee_closure_glossy(N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
+ vec3 vN = mat3(ViewMatrix) * N;
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec * color.rgb;
+ closure_load_ssr_data(ssr_spec * color.rgb, roughness, N, viewCameraVec, int(ssr_id), result);
+}
+#else
+/* Stub glossy because it is not compatible with volumetrics. */
+# define node_bsdf_glossy
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl
new file mode 100644
index 00000000000..3b23ac976ae
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_hair_info.glsl
@@ -0,0 +1,21 @@
+void node_hair_info(out float is_strand,
+ out float intercept,
+ out float thickness,
+ out vec3 tangent,
+ out float random)
+{
+#ifdef HAIR_SHADER
+ is_strand = 1.0;
+ intercept = hairTime;
+ thickness = hairThickness;
+ tangent = normalize(worldNormal);
+ random = wang_hash_noise(
+ uint(hairStrandID)); /* TODO: could be precomputed per strand instead. */
+#else
+ is_strand = 0.0;
+ intercept = 0.0;
+ thickness = 0.0;
+ tangent = vec3(1.0);
+ random = 0.0;
+#endif
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl
new file mode 100644
index 00000000000..86191451e5f
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_hash.glsl
@@ -0,0 +1,217 @@
+/* ***** Jenkins Lookup3 Hash Functions ***** */
+
+/* Source: http://burtleburtle.net/bob/c/lookup3.c */
+
+#define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k))))
+
+#define mix(a, b, c) \
+ { \
+ a -= c; \
+ a ^= rot(c, 4); \
+ c += b; \
+ b -= a; \
+ b ^= rot(a, 6); \
+ a += c; \
+ c -= b; \
+ c ^= rot(b, 8); \
+ b += a; \
+ a -= c; \
+ a ^= rot(c, 16); \
+ c += b; \
+ b -= a; \
+ b ^= rot(a, 19); \
+ a += c; \
+ c -= b; \
+ c ^= rot(b, 4); \
+ b += a; \
+ }
+
+#define final(a, b, c) \
+ { \
+ c ^= b; \
+ c -= rot(b, 14); \
+ a ^= c; \
+ a -= rot(c, 11); \
+ b ^= a; \
+ b -= rot(a, 25); \
+ c ^= b; \
+ c -= rot(b, 16); \
+ a ^= c; \
+ a -= rot(c, 4); \
+ b ^= a; \
+ b -= rot(a, 14); \
+ c ^= b; \
+ c -= rot(b, 24); \
+ }
+
+uint hash_uint(uint kx)
+{
+ uint a, b, c;
+ a = b = c = 0xdeadbeefu + (1u << 2u) + 13u;
+
+ a += kx;
+ final(a, b, c);
+
+ return c;
+}
+
+uint hash_uint2(uint kx, uint ky)
+{
+ uint a, b, c;
+ a = b = c = 0xdeadbeefu + (2u << 2u) + 13u;
+
+ b += ky;
+ a += kx;
+ final(a, b, c);
+
+ return c;
+}
+
+uint hash_uint3(uint kx, uint ky, uint kz)
+{
+ uint a, b, c;
+ a = b = c = 0xdeadbeefu + (3u << 2u) + 13u;
+
+ c += kz;
+ b += ky;
+ a += kx;
+ final(a, b, c);
+
+ return c;
+}
+
+uint hash_uint4(uint kx, uint ky, uint kz, uint kw)
+{
+ uint a, b, c;
+ a = b = c = 0xdeadbeefu + (4u << 2u) + 13u;
+
+ a += kx;
+ b += ky;
+ c += kz;
+ mix(a, b, c);
+
+ a += kw;
+ final(a, b, c);
+
+ return c;
+}
+
+#undef rot
+#undef final
+#undef mix
+
+uint hash_int(int kx)
+{
+ return hash_uint(uint(kx));
+}
+
+uint hash_int2(int kx, int ky)
+{
+ return hash_uint2(uint(kx), uint(ky));
+}
+
+uint hash_int3(int kx, int ky, int kz)
+{
+ return hash_uint3(uint(kx), uint(ky), uint(kz));
+}
+
+uint hash_int4(int kx, int ky, int kz, int kw)
+{
+ return hash_uint4(uint(kx), uint(ky), uint(kz), uint(kw));
+}
+
+/* Hashing uint or uint[234] into a float in the range [0, 1]. */
+
+float hash_uint_to_float(uint kx)
+{
+ return float(hash_uint(kx)) / float(0xFFFFFFFFu);
+}
+
+float hash_uint2_to_float(uint kx, uint ky)
+{
+ return float(hash_uint2(kx, ky)) / float(0xFFFFFFFFu);
+}
+
+float hash_uint3_to_float(uint kx, uint ky, uint kz)
+{
+ return float(hash_uint3(kx, ky, kz)) / float(0xFFFFFFFFu);
+}
+
+float hash_uint4_to_float(uint kx, uint ky, uint kz, uint kw)
+{
+ return float(hash_uint4(kx, ky, kz, kw)) / float(0xFFFFFFFFu);
+}
+
+/* Hashing float or vec[234] into a float in the range [0, 1]. */
+
+float hash_float_to_float(float k)
+{
+ return hash_uint_to_float(floatBitsToUint(k));
+}
+
+float hash_vec2_to_float(vec2 k)
+{
+ return hash_uint2_to_float(floatBitsToUint(k.x), floatBitsToUint(k.y));
+}
+
+float hash_vec3_to_float(vec3 k)
+{
+ return hash_uint3_to_float(floatBitsToUint(k.x), floatBitsToUint(k.y), floatBitsToUint(k.z));
+}
+
+float hash_vec4_to_float(vec4 k)
+{
+ return hash_uint4_to_float(
+ floatBitsToUint(k.x), floatBitsToUint(k.y), floatBitsToUint(k.z), floatBitsToUint(k.w));
+}
+
+/* Hashing vec[234] into vec[234] of components in the range [0, 1]. */
+
+vec2 hash_vec2_to_vec2(vec2 k)
+{
+ return vec2(hash_vec2_to_float(k), hash_vec3_to_float(vec3(k, 1.0)));
+}
+
+vec3 hash_vec3_to_vec3(vec3 k)
+{
+ return vec3(
+ hash_vec3_to_float(k), hash_vec4_to_float(vec4(k, 1.0)), hash_vec4_to_float(vec4(k, 2.0)));
+}
+
+vec4 hash_vec4_to_vec4(vec4 k)
+{
+ return vec4(hash_vec4_to_float(k.xyzw),
+ hash_vec4_to_float(k.wxyz),
+ hash_vec4_to_float(k.zwxy),
+ hash_vec4_to_float(k.yzwx));
+}
+
+/* Hashing float or vec[234] into vec3 of components in range [0, 1]. */
+
+vec3 hash_float_to_vec3(float k)
+{
+ return vec3(
+ hash_float_to_float(k), hash_vec2_to_float(vec2(k, 1.0)), hash_vec2_to_float(vec2(k, 2.0)));
+}
+
+vec3 hash_vec2_to_vec3(vec2 k)
+{
+ return vec3(
+ hash_vec2_to_float(k), hash_vec3_to_float(vec3(k, 1.0)), hash_vec3_to_float(vec3(k, 2.0)));
+}
+
+vec3 hash_vec4_to_vec3(vec4 k)
+{
+ return vec3(hash_vec4_to_float(k.xyzw), hash_vec4_to_float(k.zxwy), hash_vec4_to_float(k.wzyx));
+}
+
+/* Other Hash Functions */
+
+float integer_noise(int n)
+{
+ int nn;
+ n = (n + 1013) & 0x7fffffff;
+ n = (n >> 13) ^ n;
+ nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
+ return 0.5 * (float(nn) / 1073741824.0);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_holdout.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_holdout.glsl
new file mode 100644
index 00000000000..50ce2bf2ab8
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_holdout.glsl
@@ -0,0 +1,8 @@
+void node_holdout(out Closure result)
+{
+ result = CLOSURE_DEFAULT;
+#ifndef VOLUMETRICS
+ result.holdout = 1.0;
+ result.flag = CLOSURE_HOLDOUT_FLAG;
+#endif
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_hue_sat_val.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_hue_sat_val.glsl
new file mode 100644
index 00000000000..64ac73ecdf3
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_hue_sat_val.glsl
@@ -0,0 +1,14 @@
+void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol)
+{
+ vec4 hsv;
+
+ rgb_to_hsv(col, hsv);
+
+ hsv[0] = fract(hsv[0] + hue + 0.5);
+ hsv[1] = clamp(hsv[1] * sat, 0.0, 1.0);
+ hsv[2] = hsv[2] * value;
+
+ hsv_to_rgb(hsv, outcol);
+
+ outcol = mix(col, outcol, fac);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_invert.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_invert.glsl
new file mode 100644
index 00000000000..5cf362a9947
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_invert.glsl
@@ -0,0 +1,5 @@
+void invert(float fac, vec4 col, out vec4 outcol)
+{
+ outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac);
+ outcol.w = col.w;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_layer_weight.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_layer_weight.glsl
new file mode 100644
index 00000000000..588d295bcc4
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_layer_weight.glsl
@@ -0,0 +1,19 @@
+void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing)
+{
+ N = normalize(N);
+
+ /* fresnel */
+ float eta = max(1.0 - blend, 0.00001);
+ vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0);
+
+ fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta);
+
+ /* facing */
+ facing = abs(dot(I_view, N));
+ if (blend != 0.5) {
+ blend = clamp(blend, 0.0, 0.99999);
+ blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend);
+ facing = pow(facing, blend);
+ }
+ facing = 1.0 - facing;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_light_falloff.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_light_falloff.glsl
new file mode 100644
index 00000000000..f3eae653f95
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_light_falloff.glsl
@@ -0,0 +1,7 @@
+void node_light_falloff(
+ float strength, float tsmooth, out float quadratic, out float linear, out float constant)
+{
+ quadratic = strength;
+ linear = strength;
+ constant = strength;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl
new file mode 100644
index 00000000000..50c87e3f105
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_light_path.glsl
@@ -0,0 +1,31 @@
+void node_light_path(out float is_camera_ray,
+ out float is_shadow_ray,
+ out float is_diffuse_ray,
+ out float is_glossy_ray,
+ out float is_singular_ray,
+ out float is_reflection_ray,
+ out float is_transmission_ray,
+ out float ray_length,
+ out float ray_depth,
+ out float diffuse_depth,
+ out float glossy_depth,
+ out float transparent_depth,
+ out float transmission_depth)
+{
+ /* Supported. */
+ is_camera_ray = (rayType == EEVEE_RAY_CAMERA) ? 1.0 : 0.0;
+ is_shadow_ray = (rayType == EEVEE_RAY_SHADOW) ? 1.0 : 0.0;
+ is_diffuse_ray = (rayType == EEVEE_RAY_DIFFUSE) ? 1.0 : 0.0;
+ is_glossy_ray = (rayType == EEVEE_RAY_GLOSSY) ? 1.0 : 0.0;
+ /* Kind of supported. */
+ is_singular_ray = is_glossy_ray;
+ is_reflection_ray = is_glossy_ray;
+ is_transmission_ray = is_glossy_ray;
+ ray_depth = rayDepth;
+ diffuse_depth = (is_diffuse_ray == 1.0) ? rayDepth : 0.0;
+ glossy_depth = (is_glossy_ray == 1.0) ? rayDepth : 0.0;
+ transmission_depth = (is_transmission_ray == 1.0) ? glossy_depth : 0.0;
+ /* Not supported. */
+ ray_length = 1.0;
+ transparent_depth = 0.0;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_map_range.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_map_range.glsl
new file mode 100644
index 00000000000..a185774f4b3
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_map_range.glsl
@@ -0,0 +1,10 @@
+void map_range(
+ float value, float fromMin, float fromMax, float toMin, float toMax, out float result)
+{
+ if (fromMax != fromMin) {
+ result = toMin + ((value - fromMin) / (fromMax - fromMin)) * (toMax - toMin);
+ }
+ else {
+ result = 0.0;
+ }
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl
new file mode 100644
index 00000000000..ef47ac2be98
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_mapping.glsl
@@ -0,0 +1,7 @@
+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;
+ outvec = clamp(outvec, minvec, maxvec);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_math.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_math.glsl
new file mode 100644
index 00000000000..4fac770e8fe
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_math.glsl
@@ -0,0 +1,130 @@
+void math_add(float a, float b, out float result)
+{
+ result = a + b;
+}
+
+void math_subtract(float a, float b, out float result)
+{
+ result = a - b;
+}
+
+void math_multiply(float a, float b, out float result)
+{
+ result = a * b;
+}
+
+void math_divide(float a, float b, out float result)
+{
+ result = safe_divide(a, b);
+}
+
+void math_power(float a, float b, out float result)
+{
+ if (a >= 0.0) {
+ result = compatible_pow(a, b);
+ }
+ else {
+ float fraction = mod(abs(b), 1.0);
+ if (fraction > 0.999 || fraction < 0.001) {
+ result = compatible_pow(a, floor(b + 0.5));
+ }
+ else {
+ result = 0.0;
+ }
+ }
+}
+
+void math_logarithm(float a, float b, out float result)
+{
+ result = (a > 0.0 && b > 0.0) ? log2(a) / log2(b) : 0.0;
+}
+
+void math_sqrt(float a, float b, out float result)
+{
+ result = (a > 0.0) ? sqrt(a) : 0.0;
+}
+
+void math_absolute(float a, float b, out float result)
+{
+ result = abs(a);
+}
+
+void math_minimum(float a, float b, out float result)
+{
+ result = min(a, b);
+}
+
+void math_maximum(float a, float b, out float result)
+{
+ result = max(a, b);
+}
+
+void math_less_than(float a, float b, out float result)
+{
+ result = (a < b) ? 1.0 : 0.0;
+}
+
+void math_greater_than(float a, float b, out float result)
+{
+ result = (a > b) ? 1.0 : 0.0;
+}
+
+void math_round(float a, float b, out float result)
+{
+ result = floor(a + 0.5);
+}
+
+void math_floor(float a, float b, out float result)
+{
+ result = floor(a);
+}
+
+void math_ceil(float a, float b, out float result)
+{
+ result = ceil(a);
+}
+
+void math_fraction(float a, float b, out float result)
+{
+ result = a - floor(a);
+}
+
+void math_modulo(float a, float b, out float result)
+{
+ result = c_mod(a, b);
+}
+
+void math_sine(float a, float b, out float result)
+{
+ result = sin(a);
+}
+
+void math_cosine(float a, float b, out float result)
+{
+ result = cos(a);
+}
+
+void math_tangent(float a, float b, out float result)
+{
+ result = tan(a);
+}
+
+void math_arcsine(float a, float b, out float result)
+{
+ result = (a <= 1.0 && a >= -1.0) ? asin(a) : 0.0;
+}
+
+void math_arccosine(float a, float b, out float result)
+{
+ result = (a <= 1.0 && a >= -1.0) ? acos(a) : 0.0;
+}
+
+void math_arctangent(float a, float b, out float result)
+{
+ result = atan(a);
+}
+
+void math_arctan2(float a, float b, out float result)
+{
+ result = atan(a, b);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl
new file mode 100644
index 00000000000..0be7da0cc4c
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_math_util.glsl
@@ -0,0 +1,101 @@
+/* Float Math */
+
+float safe_divide(float a, float b)
+{
+ return (b != 0.0) ? a / b : 0.0;
+}
+
+/* Modulo with C sign convention. mod in GLSL will take absolute for negative numbers. */
+float c_mod(float a, float b)
+{
+ return (b != 0.0 && a != b) ? sign(a) * mod(abs(a), b) : 0.0;
+}
+
+float compatible_pow(float x, float y)
+{
+ if (y == 0.0) { /* x^0 -> 1, including 0^0 */
+ return 1.0;
+ }
+
+ /* glsl pow doesn't accept negative x */
+ if (x < 0.0) {
+ if (mod(-y, 2.0) == 0.0) {
+ return pow(-x, y);
+ }
+ else {
+ return -pow(-x, y);
+ }
+ }
+ else if (x == 0.0) {
+ return 0.0;
+ }
+
+ return pow(x, y);
+}
+
+float hypot(float x, float y)
+{
+ return sqrt(x * x + y * y);
+}
+
+int floor_to_int(float x)
+{
+ return int(floor(x));
+}
+
+int quick_floor(float x)
+{
+ return int(x) - ((x < 0) ? 1 : 0);
+}
+
+float floorfrac(float x, out int i)
+{
+ float x_floor = floor(x);
+ i = int(x_floor);
+ return x - x_floor;
+}
+
+/* Vector Math */
+
+vec3 safe_divide(vec3 a, vec3 b)
+{
+ return vec3(safe_divide(a.x, b.x), safe_divide(a.y, b.y), safe_divide(a.z, b.z));
+}
+
+vec3 c_mod(vec3 a, vec3 b)
+{
+ return vec3(c_mod(a.x, b.x), c_mod(a.y, b.y), c_mod(a.z, b.z));
+}
+
+void vector_mix(float strength, vec3 a, vec3 b, out vec3 outVector)
+{
+ outVector = strength * a + (1 - strength) * b;
+}
+
+void invert_z(vec3 v, out vec3 outv)
+{
+ v.z = -v.z;
+ outv = v;
+}
+
+void vector_normalize(vec3 normal, out vec3 outnormal)
+{
+ outnormal = normalize(normal);
+}
+
+/* Matirx Math */
+
+void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout)
+{
+ vout = (mat * vec4(vin, 0.0)).xyz;
+}
+
+void normal_transform_transposed_m4v3(vec3 vin, mat4 mat, out vec3 vout)
+{
+ vout = transpose(mat3(mat)) * vin;
+}
+
+void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout)
+{
+ vout = (mat * vec4(vin, 1.0)).xyz;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl
new file mode 100644
index 00000000000..abe6081489d
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_mix_rgb.glsl
@@ -0,0 +1,291 @@
+void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ outcol = mix(col1, col2, fac);
+ outcol.a = col1.a;
+}
+
+void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ outcol = mix(col1, col1 + col2, fac);
+ outcol.a = col1.a;
+}
+
+void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ outcol = mix(col1, col1 * col2, fac);
+ outcol.a = col1.a;
+}
+
+void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ float facm = 1.0 - fac;
+
+ outcol = vec4(1.0) - (vec4(facm) + fac * (vec4(1.0) - col2)) * (vec4(1.0) - col1);
+ outcol.a = col1.a;
+}
+
+void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ float facm = 1.0 - fac;
+
+ outcol = col1;
+
+ if (outcol.r < 0.5) {
+ outcol.r *= facm + 2.0 * fac * col2.r;
+ }
+ else {
+ outcol.r = 1.0 - (facm + 2.0 * fac * (1.0 - col2.r)) * (1.0 - outcol.r);
+ }
+
+ if (outcol.g < 0.5) {
+ outcol.g *= facm + 2.0 * fac * col2.g;
+ }
+ else {
+ outcol.g = 1.0 - (facm + 2.0 * fac * (1.0 - col2.g)) * (1.0 - outcol.g);
+ }
+
+ if (outcol.b < 0.5) {
+ outcol.b *= facm + 2.0 * fac * col2.b;
+ }
+ else {
+ outcol.b = 1.0 - (facm + 2.0 * fac * (1.0 - col2.b)) * (1.0 - outcol.b);
+ }
+}
+
+void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ outcol = mix(col1, col1 - col2, fac);
+ outcol.a = col1.a;
+}
+
+void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ float facm = 1.0 - fac;
+
+ outcol = col1;
+
+ if (col2.r != 0.0) {
+ outcol.r = facm * outcol.r + fac * outcol.r / col2.r;
+ }
+ if (col2.g != 0.0) {
+ outcol.g = facm * outcol.g + fac * outcol.g / col2.g;
+ }
+ if (col2.b != 0.0) {
+ outcol.b = facm * outcol.b + fac * outcol.b / col2.b;
+ }
+}
+
+void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ outcol = mix(col1, abs(col1 - col2), fac);
+ outcol.a = col1.a;
+}
+
+void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ outcol.rgb = min(col1.rgb, col2.rgb * fac);
+ outcol.a = col1.a;
+}
+
+void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ outcol.rgb = max(col1.rgb, col2.rgb * fac);
+ outcol.a = col1.a;
+}
+
+void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ outcol = col1;
+
+ if (outcol.r != 0.0) {
+ float tmp = 1.0 - fac * col2.r;
+ if (tmp <= 0.0) {
+ outcol.r = 1.0;
+ }
+ else if ((tmp = outcol.r / tmp) > 1.0) {
+ outcol.r = 1.0;
+ }
+ else {
+ outcol.r = tmp;
+ }
+ }
+ if (outcol.g != 0.0) {
+ float tmp = 1.0 - fac * col2.g;
+ if (tmp <= 0.0) {
+ outcol.g = 1.0;
+ }
+ else if ((tmp = outcol.g / tmp) > 1.0) {
+ outcol.g = 1.0;
+ }
+ else {
+ outcol.g = tmp;
+ }
+ }
+ if (outcol.b != 0.0) {
+ float tmp = 1.0 - fac * col2.b;
+ if (tmp <= 0.0) {
+ outcol.b = 1.0;
+ }
+ else if ((tmp = outcol.b / tmp) > 1.0) {
+ outcol.b = 1.0;
+ }
+ else {
+ outcol.b = tmp;
+ }
+ }
+}
+
+void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ float tmp, facm = 1.0 - fac;
+
+ outcol = col1;
+
+ tmp = facm + fac * col2.r;
+ if (tmp <= 0.0) {
+ outcol.r = 0.0;
+ }
+ else if ((tmp = (1.0 - (1.0 - outcol.r) / tmp)) < 0.0) {
+ outcol.r = 0.0;
+ }
+ else if (tmp > 1.0) {
+ outcol.r = 1.0;
+ }
+ else {
+ outcol.r = tmp;
+ }
+
+ tmp = facm + fac * col2.g;
+ if (tmp <= 0.0) {
+ outcol.g = 0.0;
+ }
+ else if ((tmp = (1.0 - (1.0 - outcol.g) / tmp)) < 0.0) {
+ outcol.g = 0.0;
+ }
+ else if (tmp > 1.0) {
+ outcol.g = 1.0;
+ }
+ else {
+ outcol.g = tmp;
+ }
+
+ tmp = facm + fac * col2.b;
+ if (tmp <= 0.0) {
+ outcol.b = 0.0;
+ }
+ else if ((tmp = (1.0 - (1.0 - outcol.b) / tmp)) < 0.0) {
+ outcol.b = 0.0;
+ }
+ else if (tmp > 1.0) {
+ outcol.b = 1.0;
+ }
+ else {
+ outcol.b = tmp;
+ }
+}
+
+void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ float facm = 1.0 - fac;
+
+ outcol = col1;
+
+ vec4 hsv, hsv2, tmp;
+ rgb_to_hsv(col2, hsv2);
+
+ if (hsv2.y != 0.0) {
+ rgb_to_hsv(outcol, hsv);
+ hsv.x = hsv2.x;
+ hsv_to_rgb(hsv, tmp);
+
+ outcol = mix(outcol, tmp, fac);
+ outcol.a = col1.a;
+ }
+}
+
+void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ float facm = 1.0 - fac;
+
+ outcol = col1;
+
+ vec4 hsv, hsv2;
+ rgb_to_hsv(outcol, hsv);
+
+ if (hsv.y != 0.0) {
+ rgb_to_hsv(col2, hsv2);
+
+ hsv.y = facm * hsv.y + fac * hsv2.y;
+ hsv_to_rgb(hsv, outcol);
+ }
+}
+
+void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ float facm = 1.0 - fac;
+
+ vec4 hsv, hsv2;
+ rgb_to_hsv(col1, hsv);
+ rgb_to_hsv(col2, hsv2);
+
+ hsv.z = facm * hsv.z + fac * hsv2.z;
+ hsv_to_rgb(hsv, outcol);
+}
+
+void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ float facm = 1.0 - fac;
+
+ outcol = col1;
+
+ vec4 hsv, hsv2, tmp;
+ rgb_to_hsv(col2, hsv2);
+
+ if (hsv2.y != 0.0) {
+ rgb_to_hsv(outcol, hsv);
+ hsv.x = hsv2.x;
+ hsv.y = hsv2.y;
+ hsv_to_rgb(hsv, tmp);
+
+ outcol = mix(outcol, tmp, fac);
+ outcol.a = col1.a;
+ }
+}
+
+void mix_soft(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+ float facm = 1.0 - fac;
+
+ vec4 one = vec4(1.0);
+ vec4 scr = one - (one - col2) * (one - col1);
+ outcol = facm * col1 + fac * ((one - col1) * col2 * col1 + col1 * scr);
+}
+
+void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
+{
+ fac = clamp(fac, 0.0, 1.0);
+
+ outcol = col1 + fac * (2.0 * (col2 - vec4(0.5)));
+}
+
+void clamp_color(vec3 vec, vec3 min, vec3 max, out vec3 out_vec)
+{
+ out_vec = clamp(vec, min, max);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl
new file mode 100644
index 00000000000..c303d21d7c1
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_mix_shader.glsl
@@ -0,0 +1,4 @@
+void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader)
+{
+ shader = closure_mix(shader1, shader2, fac);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl
new file mode 100644
index 00000000000..8c6a10e3fe7
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_noise.glsl
@@ -0,0 +1,74 @@
+float noise_fade(float t)
+{
+ return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
+}
+
+float noise_scale3(float result)
+{
+ return 0.9820 * result;
+}
+
+float noise_nerp(float t, float a, float b)
+{
+ return (1.0 - t) * a + t * b;
+}
+
+float noise_grad(uint hash, float x, float y, float z)
+{
+ uint h = hash & 15u;
+ float u = h < 8u ? x : y;
+ float vt = ((h == 12u) || (h == 14u)) ? x : z;
+ float v = h < 4u ? y : vt;
+ return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v);
+}
+
+float noise_perlin(float x, float y, float z)
+{
+ int X;
+ float fx = floorfrac(x, X);
+ int Y;
+ float fy = floorfrac(y, Y);
+ int Z;
+ float fz = floorfrac(z, Z);
+
+ float u = noise_fade(fx);
+ float v = noise_fade(fy);
+ float w = noise_fade(fz);
+
+ float noise_u[2], noise_v[2];
+
+ noise_u[0] = noise_nerp(u,
+ noise_grad(hash_int3(X, Y, Z), fx, fy, fz),
+ noise_grad(hash_int3(X + 1, Y, Z), fx - 1.0, fy, fz));
+
+ noise_u[1] = noise_nerp(u,
+ noise_grad(hash_int3(X, Y + 1, Z), fx, fy - 1.0, fz),
+ noise_grad(hash_int3(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz));
+
+ noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]);
+
+ noise_u[0] = noise_nerp(u,
+ noise_grad(hash_int3(X, Y, Z + 1), fx, fy, fz - 1.0),
+ noise_grad(hash_int3(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0));
+
+ noise_u[1] = noise_nerp(
+ u,
+ noise_grad(hash_int3(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0),
+ noise_grad(hash_int3(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0));
+
+ noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]);
+
+ float r = noise_scale3(noise_nerp(w, noise_v[0], noise_v[1]));
+
+ return (isinf(r)) ? 0.0 : r;
+}
+
+float noise(vec3 p)
+{
+ return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5;
+}
+
+float snoise(vec3 p)
+{
+ return noise_perlin(p.x, p.y, p.z);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_normal.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_normal.glsl
new file mode 100644
index 00000000000..4f6e68909ad
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_normal.glsl
@@ -0,0 +1,5 @@
+void normal_new_shading(vec3 nor, vec3 dir, out vec3 outnor, out float outdot)
+{
+ outnor = dir;
+ outdot = dot(normalize(nor), dir);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_normal_map.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_normal_map.glsl
new file mode 100644
index 00000000000..6930e0c5dad
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_normal_map.glsl
@@ -0,0 +1,22 @@
+void node_normal_map(vec4 info, vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal)
+{
+ if (all(equal(tangent, vec4(0.0, 0.0, 0.0, 1.0)))) {
+ outnormal = normal;
+ return;
+ }
+ tangent *= (gl_FrontFacing ? 1.0 : -1.0);
+ vec3 B = tangent.w * cross(normal, tangent.xyz) * info.w;
+
+ outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal;
+ outnormal = normalize(outnormal);
+}
+
+void color_to_normal_new_shading(vec3 color, out vec3 normal)
+{
+ normal = vec3(2.0) * color - vec3(1.0);
+}
+
+void color_to_blender_normal_new_shading(vec3 color, out vec3 normal)
+{
+ normal = vec3(2.0, -2.0, -2.0) * color - vec3(1.0);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl
new file mode 100644
index 00000000000..ff77b0beea2
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_object_info.glsl
@@ -0,0 +1,16 @@
+void node_object_info(mat4 obmat,
+ vec4 obcolor,
+ vec4 info,
+ float mat_index,
+ out vec3 location,
+ out vec4 color,
+ out float object_index,
+ out float material_index,
+ out float random)
+{
+ location = obmat[3].xyz;
+ color = obcolor;
+ object_index = info.x;
+ material_index = mat_index;
+ random = info.z;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
new file mode 100644
index 00000000000..62f76d46088
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
@@ -0,0 +1,8 @@
+void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result)
+{
+#ifdef VOLUMETRICS
+ result = volume;
+#else
+ result = surface;
+#endif
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_world.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_world.glsl
new file mode 100644
index 00000000000..ba391df185e
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_world.glsl
@@ -0,0 +1,11 @@
+uniform float backgroundAlpha;
+
+void node_output_world(Closure surface, Closure volume, out Closure result)
+{
+#ifndef VOLUMETRICS
+ result.radiance = surface.radiance * backgroundAlpha;
+ result.transmittance = vec3(1.0 - backgroundAlpha);
+#else
+ result = volume;
+#endif /* VOLUMETRICS */
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_particle_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_particle_info.glsl
new file mode 100644
index 00000000000..bdd60c20a81
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_particle_info.glsl
@@ -0,0 +1,23 @@
+void particle_info(vec4 sprops,
+ vec4 loc,
+ vec3 vel,
+ vec3 avel,
+ out float index,
+ out float random,
+ out float age,
+ out float life_time,
+ out vec3 location,
+ out float size,
+ out vec3 velocity,
+ out vec3 angular_velocity)
+{
+ index = sprops.x;
+ random = loc.w;
+ age = sprops.y;
+ life_time = sprops.z;
+ size = sprops.w;
+
+ location = loc.xyz;
+ velocity = vel;
+ angular_velocity = avel;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
new file mode 100644
index 00000000000..c6b640c572d
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl
@@ -0,0 +1,439 @@
+#ifndef VOLUMETRICS
+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,
+ vec3 basecol_tint,
+ float metallic,
+ float specular_fac,
+ float specular_tint,
+ out vec3 diffuse,
+ out vec3 f0)
+{
+ 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;
+ /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps,
+ * therefore we need to clamp value. */
+ f = clamp(f, 0.0, 1.0);
+ /* 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);
+}
+
+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,
+ vec4 emission,
+ float alpha,
+ vec3 N,
+ vec3 CN,
+ vec3 T,
+ vec3 I,
+ float ssr_id,
+ float sss_id,
+ vec3 sss_scale,
+ out Closure result)
+{
+ N = normalize(N);
+ 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;
+ 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);
+
+ /* 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);
+
+ vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
+
+ vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
+
+ float sss_scalef = avg(sss_scale) * subsurface;
+ eevee_closure_principled(N,
+ mixed_ss_base_color,
+ f0,
+ f90,
+ 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;
+
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec + out_refr;
+ result.radiance += out_diff * out_sheen; /* Coarse approx. */
+
+ closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+
+ vec3 sss_radiance = (out_diff + out_trans) * alpha;
+# ifndef USE_SSS
+ result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission);
+# else
+# ifdef USE_SSS_ALBEDO
+ vec3 sss_albedo = mixed_ss_base_color;
+# else
+ sss_radiance *= mixed_ss_base_color;
+# endif
+ sss_radiance *= (1.0 - transmission);
+ closure_load_sss_data(sss_scalef,
+ sss_radiance,
+# ifdef USE_SSS_ALBEDO
+ sss_albedo,
+# endif
+ int(sss_id),
+ result);
+# endif /* USE_SSS */
+
+ result.radiance += emission.rgb;
+ result.radiance *= alpha;
+ result.transmittance = vec3(1.0 - alpha);
+}
+
+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,
+ vec4 emission,
+ float alpha,
+ vec3 N,
+ vec3 CN,
+ vec3 T,
+ vec3 I,
+ float ssr_id,
+ float sss_id,
+ vec3 sss_scale,
+ out Closure result)
+{
+ N = normalize(N);
+ metallic = saturate(metallic);
+ float dielectric = 1.0 - metallic;
+
+ 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, vec3(1.0), int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec);
+
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec + out_diff * (diffuse + out_sheen);
+ closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+ result.radiance += emission.rgb;
+ result.radiance *= alpha;
+ result.transmittance = vec3(1.0 - alpha);
+}
+
+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,
+ vec4 emission,
+ float alpha,
+ vec3 N,
+ vec3 CN,
+ vec3 T,
+ vec3 I,
+ float ssr_id,
+ float sss_id,
+ vec3 sss_scale,
+ out Closure result)
+{
+ N = normalize(N);
+ vec3 out_spec, ssr_spec;
+
+ vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
+
+ eevee_closure_glossy(N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
+
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec;
+ closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+ result.radiance += emission.rgb;
+ result.radiance *= alpha;
+ result.transmittance = vec3(1.0 - alpha);
+}
+
+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,
+ vec4 emission,
+ float alpha,
+ 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;
+ N = normalize(N);
+
+ vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
+
+ eevee_closure_clearcoat(N,
+ base_color.rgb,
+ f90,
+ int(ssr_id),
+ roughness,
+ CN,
+ clearcoat * 0.25,
+ clearcoat_roughness,
+ 1.0,
+ out_spec,
+ ssr_spec);
+
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec;
+ closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+ result.radiance += emission.rgb;
+ result.radiance *= alpha;
+ result.transmittance = vec3(1.0 - alpha);
+}
+
+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,
+ vec4 emission,
+ float alpha,
+ vec3 N,
+ vec3 CN,
+ vec3 T,
+ vec3 I,
+ float ssr_id,
+ float sss_id,
+ vec3 sss_scale,
+ out Closure result)
+{
+ metallic = saturate(metallic);
+ N = normalize(N);
+
+ 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 = avg(sss_scale) * subsurface;
+
+ float NV = dot(N, cameraVec);
+ vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
+
+ vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
+
+ eevee_closure_skin(N,
+ mixed_ss_base_color,
+ f0,
+ f90,
+ int(ssr_id),
+ roughness,
+ 1.0,
+ sss_scalef,
+ out_diff,
+ out_trans,
+ out_spec,
+ ssr_spec);
+
+ result = CLOSURE_DEFAULT;
+ result.radiance = out_spec;
+ closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+
+ vec3 sss_radiance = (out_diff + out_trans) * alpha;
+# ifndef USE_SSS
+ result.radiance += sss_radiance * mixed_ss_base_color * (1.0 - transmission);
+# else
+# ifdef USE_SSS_ALBEDO
+ vec3 sss_albedo = mixed_ss_base_color;
+# else
+ sss_radiance *= mixed_ss_base_color;
+# endif
+ sss_radiance *= (1.0 - transmission);
+ closure_load_sss_data(sss_scalef,
+ sss_radiance,
+# ifdef USE_SSS_ALBEDO
+ sss_albedo,
+# endif
+ int(sss_id),
+ result);
+# endif /* USE_SSS */
+
+ result.radiance += out_diff * out_sheen;
+ result.radiance += emission.rgb;
+ result.radiance *= alpha;
+ result.transmittance = vec3(1.0 - alpha);
+}
+
+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,
+ vec4 emission,
+ float alpha,
+ 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);
+ N = normalize(N);
+
+ 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), 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;
+
+ result = CLOSURE_DEFAULT;
+ result.radiance = mix(out_refr, out_spec, fresnel);
+ closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result);
+ result.radiance += emission.rgb;
+ result.radiance *= alpha;
+ result.transmittance = vec3(1.0 - alpha);
+}
+#else
+/* Stub principled because it is not compatible with volumetrics. */
+# define node_bsdf_principled
+# define node_bsdf_principled_dielectric
+# define node_bsdf_principled_metallic
+# define node_bsdf_principled_clearcoat
+# define node_bsdf_principled_subsurface
+# define node_bsdf_principled_glass
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
new file mode 100644
index 00000000000..04394a9420b
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_refraction.glsl
@@ -0,0 +1,16 @@
+#ifndef VOLUMETRICS
+void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result)
+{
+ N = normalize(N);
+ vec3 out_refr;
+ color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */
+ eevee_closure_refraction(N, roughness, ior, out_refr);
+ vec3 vN = mat3(ViewMatrix) * N;
+ result = CLOSURE_DEFAULT;
+ result.ssr_normal = normal_encode(vN, viewCameraVec);
+ result.radiance = out_refr * color.rgb;
+}
+#else
+/* Stub refraction because it is not compatible with volumetrics. */
+# define node_bsdf_refraction
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl
new file mode 100644
index 00000000000..054fdddf7c3
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_curves.glsl
@@ -0,0 +1,73 @@
+/* ext is vec4(in_x, in_dy, out_x, out_dy). */
+float curve_extrapolate(float x, float y, vec4 ext)
+{
+ if (x < 0.0) {
+ return y + x * ext.y;
+ }
+ else if (x > 1.0) {
+ return y + (x - 1.0) * ext.w;
+ }
+ else {
+ return y;
+ }
+}
+
+#define RANGE_RESCALE(x, min, range) ((x - min) * range)
+
+void curves_rgb(float fac,
+ vec4 col,
+ sampler1DArray curvemap,
+ float layer,
+ vec4 range,
+ vec4 ext_r,
+ vec4 ext_g,
+ vec4 ext_b,
+ vec4 ext_a,
+ out vec4 outcol)
+{
+ vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer);
+ vec3 samp;
+ samp.r = texture(curvemap, co.xw).a;
+ samp.g = texture(curvemap, co.yw).a;
+ samp.b = texture(curvemap, co.zw).a;
+
+ samp.r = curve_extrapolate(co.x, samp.r, ext_a);
+ samp.g = curve_extrapolate(co.y, samp.g, ext_a);
+ samp.b = curve_extrapolate(co.z, samp.b, ext_a);
+
+ vec3 rgb_min = vec3(ext_r.x, ext_g.x, ext_b.x);
+ co.xyz = RANGE_RESCALE(samp.rgb, rgb_min, range.rgb);
+
+ samp.r = texture(curvemap, co.xw).r;
+ samp.g = texture(curvemap, co.yw).g;
+ samp.b = texture(curvemap, co.zw).b;
+
+ outcol.r = curve_extrapolate(co.x, samp.r, ext_r);
+ outcol.g = curve_extrapolate(co.y, samp.g, ext_g);
+ outcol.b = curve_extrapolate(co.z, samp.b, ext_b);
+ outcol.a = col.a;
+
+ outcol = mix(col, outcol, fac);
+}
+
+void curves_rgb_opti(float fac,
+ vec4 col,
+ sampler1DArray curvemap,
+ float layer,
+ vec4 range,
+ vec4 ext_a,
+ out vec4 outcol)
+{
+ vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer);
+ vec3 samp;
+ samp.r = texture(curvemap, co.xw).a;
+ samp.g = texture(curvemap, co.yw).a;
+ samp.b = texture(curvemap, co.zw).a;
+
+ outcol.r = curve_extrapolate(co.x, samp.r, ext_a);
+ outcol.g = curve_extrapolate(co.y, samp.g, ext_a);
+ outcol.b = curve_extrapolate(co.z, samp.b, ext_a);
+ outcol.a = col.a;
+
+ outcol = mix(col, outcol, fac);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_rgb_to_bw.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_to_bw.glsl
new file mode 100644
index 00000000000..ceca02a2356
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_rgb_to_bw.glsl
@@ -0,0 +1,5 @@
+void rgbtobw(vec4 color, out float outval)
+{
+ vec3 factors = vec3(0.2126, 0.7152, 0.0722);
+ outval = dot(color.rgb, factors);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_separate_hsv.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_separate_hsv.glsl
new file mode 100644
index 00000000000..fb64e424c6c
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_separate_hsv.glsl
@@ -0,0 +1,9 @@
+void separate_hsv(vec4 col, out float h, out float s, out float v)
+{
+ vec4 hsv;
+
+ rgb_to_hsv(col, hsv);
+ h = hsv[0];
+ s = hsv[1];
+ v = hsv[2];
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_separate_rgb.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_separate_rgb.glsl
new file mode 100644
index 00000000000..4232b4c001e
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_separate_rgb.glsl
@@ -0,0 +1,6 @@
+void separate_rgb(vec4 col, out float r, out float g, out float b)
+{
+ r = col.r;
+ g = col.g;
+ b = col.b;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_separate_xyz.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_separate_xyz.glsl
new file mode 100644
index 00000000000..fac29ccc135
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_separate_xyz.glsl
@@ -0,0 +1,6 @@
+void separate_xyz(vec3 vec, out float x, out float y, out float z)
+{
+ x = vec.r;
+ y = vec.g;
+ z = vec.b;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_set.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_set.glsl
new file mode 100644
index 00000000000..dc2ecb05351
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_set.glsl
@@ -0,0 +1,44 @@
+void set_value(float val, out float outval)
+{
+ outval = val;
+}
+
+void set_rgb(vec3 col, out vec3 outcol)
+{
+ outcol = col;
+}
+
+void set_rgba(vec4 col, out vec4 outcol)
+{
+ outcol = col;
+}
+
+void set_value_zero(out float outval)
+{
+ outval = 0.0;
+}
+
+void set_value_one(out float outval)
+{
+ outval = 1.0;
+}
+
+void set_rgb_zero(out vec3 outval)
+{
+ outval = vec3(0.0);
+}
+
+void set_rgb_one(out vec3 outval)
+{
+ outval = vec3(1.0);
+}
+
+void set_rgba_zero(out vec4 outval)
+{
+ outval = vec4(0.0);
+}
+
+void set_rgba_one(out vec4 outval)
+{
+ outval = vec4(1.0);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl
new file mode 100644
index 00000000000..0a587c7e471
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_shader_to_rgba.glsl
@@ -0,0 +1,25 @@
+#ifndef VOLUMETRICS
+void node_shader_to_rgba(Closure cl, out vec4 outcol, out float outalpha)
+{
+ vec4 spec_accum = vec4(0.0);
+ if (ssrToggle && FLAG_TEST(cl.flag, CLOSURE_SSR_FLAG)) {
+ vec3 V = cameraVec;
+ vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec);
+ vec3 N = transform_direction(ViewMatrixInverse, vN);
+ float roughness = cl.ssr_data.a;
+ float roughnessSquared = max(1e-3, roughness * roughness);
+ fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum);
+ }
+
+ outalpha = avg(cl.transmittance);
+ outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0);
+
+# ifdef USE_SSS
+# ifdef USE_SSS_ALBEDO
+ outcol.rgb += cl.sss_data.rgb * cl.sss_albedo;
+# else
+ outcol.rgb += cl.sss_data.rgb;
+# endif
+# endif
+}
+#endif /* VOLUMETRICS */
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_squeeze.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_squeeze.glsl
new file mode 100644
index 00000000000..b73bdebf7f6
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_squeeze.glsl
@@ -0,0 +1,4 @@
+void squeeze(float val, float width, float center, out float outval)
+{
+ outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width)));
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
new file mode 100644
index 00000000000..fc81f3c4674
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_subsurface_scattering.glsl
@@ -0,0 +1,42 @@
+#ifndef VOLUMETRICS
+void node_subsurface_scattering(vec4 color,
+ float scale,
+ vec3 radius,
+ float sharpen,
+ float texture_blur,
+ vec3 N,
+ float sss_id,
+ out Closure result)
+{
+# if defined(USE_SSS)
+ N = normalize(N);
+ vec3 out_diff, out_trans;
+ vec3 vN = mat3(ViewMatrix) * N;
+ result = CLOSURE_DEFAULT;
+ closure_load_ssr_data(vec3(0.0), 0.0, N, viewCameraVec, -1, result);
+
+ eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans);
+
+ vec3 sss_radiance = out_diff + out_trans;
+# ifdef USE_SSS_ALBEDO
+ /* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */
+ vec3 sss_albedo = mix(color.rgb, vec3(1.0), texture_blur);
+ sss_radiance *= mix(vec3(1.0), color.rgb, texture_blur);
+# else
+ sss_radiance *= color.rgb;
+# endif
+ closure_load_sss_data(scale,
+ sss_radiance,
+# ifdef USE_SSS_ALBEDO
+ sss_albedo,
+# endif
+ int(sss_id),
+ result);
+# else
+ node_bsdf_diffuse(color, 0.0, N, result);
+# endif
+}
+#else
+/* Stub subsurface scattering because it is not compatible with volumetrics. */
+# define node_subsurface_scattering
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tangent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tangent.glsl
new file mode 100644
index 00000000000..ff2dbc7ead3
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tangent.glsl
@@ -0,0 +1,25 @@
+void tangent_orco_x(vec3 orco_in, out vec3 orco_out)
+{
+ orco_out = orco_in.xzy * vec3(0.0, -0.5, 0.5) + vec3(0.0, 0.25, -0.25);
+}
+
+void tangent_orco_y(vec3 orco_in, out vec3 orco_out)
+{
+ orco_out = orco_in.zyx * vec3(-0.5, 0.0, 0.5) + vec3(0.25, 0.0, -0.25);
+}
+
+void tangent_orco_z(vec3 orco_in, out vec3 orco_out)
+{
+ orco_out = orco_in.yxz * vec3(-0.5, 0.5, 0.0) + vec3(0.25, -0.25, 0.0);
+}
+
+void node_tangentmap(vec4 attr_tangent, out vec3 tangent)
+{
+ tangent = normalize(attr_tangent.xyz);
+}
+
+void node_tangent(vec3 N, vec3 orco, mat4 objmat, out vec3 T)
+{
+ T = (objmat * vec4(orco, 0.0)).xyz;
+ T = cross(N, normalize(cross(T, N)));
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl
new file mode 100644
index 00000000000..e252e5ba726
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_brick.glsl
@@ -0,0 +1,78 @@
+vec2 calc_brick_texture(vec3 p,
+ float mortar_size,
+ float mortar_smooth,
+ float bias,
+ float brick_width,
+ float row_height,
+ float offset_amount,
+ int offset_frequency,
+ float squash_amount,
+ int squash_frequency)
+{
+ int bricknum, rownum;
+ float offset = 0.0;
+ float x, y;
+
+ rownum = floor_to_int(p.y / row_height);
+
+ if (offset_frequency != 0 && squash_frequency != 0) {
+ brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */
+ offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */
+ }
+
+ bricknum = floor_to_int((p.x + offset) / brick_width);
+
+ x = (p.x + offset) - brick_width * bricknum;
+ y = p.y - row_height * rownum;
+
+ float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0);
+
+ float min_dist = min(min(x, y), min(brick_width - x, row_height - y));
+ if (min_dist >= mortar_size) {
+ return vec2(tint, 0.0);
+ }
+ else if (mortar_smooth == 0.0) {
+ return vec2(tint, 1.0);
+ }
+ else {
+ min_dist = 1.0 - min_dist / mortar_size;
+ return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist));
+ }
+}
+
+void node_tex_brick(vec3 co,
+ vec4 color1,
+ vec4 color2,
+ vec4 mortar,
+ float scale,
+ float mortar_size,
+ float mortar_smooth,
+ float bias,
+ float brick_width,
+ float row_height,
+ float offset_amount,
+ float offset_frequency,
+ float squash_amount,
+ float squash_frequency,
+ out vec4 color,
+ out float fac)
+{
+ vec2 f2 = calc_brick_texture(co * scale,
+ mortar_size,
+ mortar_smooth,
+ bias,
+ brick_width,
+ row_height,
+ offset_amount,
+ int(offset_frequency),
+ squash_amount,
+ int(squash_frequency));
+ float tint = f2.x;
+ float f = f2.y;
+ if (f != 1.0) {
+ float facm = 1.0 - tint;
+ color1 = facm * color1 + tint * color2;
+ }
+ color = mix(color1, mortar, f);
+ fac = f;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl
new file mode 100644
index 00000000000..f534f3bddf3
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_checker.glsl
@@ -0,0 +1,17 @@
+void node_tex_checker(
+ vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac)
+{
+ vec3 p = co * scale;
+
+ /* Prevent precision issues on unit coordinates. */
+ p = (p + 0.000001) * 0.999999;
+
+ int xi = int(abs(floor(p.x)));
+ int yi = int(abs(floor(p.y)));
+ int zi = int(abs(floor(p.z)));
+
+ bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2)));
+
+ color = check ? color1 : color2;
+ fac = check ? 1.0 : 0.0;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
new file mode 100644
index 00000000000..9bd36f8a757
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
@@ -0,0 +1,44 @@
+void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec)
+{
+#ifdef MESH_SHADER
+ worldvec = worldPosition;
+#else
+ vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (ProjectionMatrixInverse * v);
+
+ vec3 co = co_homogenous.xyz / co_homogenous.w;
+# if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ worldvec = mat3(ViewMatrixInverse) * co;
+# else
+ worldvec = mat3(ModelMatrixInverse) * (mat3(ViewMatrixInverse) * co);
+# endif
+#endif
+}
+
+void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv)
+{
+ vec3 nco = normalize(co);
+ uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5;
+ uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5;
+
+ /* Fix pole bleeding */
+ float half_height = clamp_size / float(textureSize(ima, 0).y);
+ uv.y = clamp(uv.y, half_height, 1.0 - half_height);
+ uv.z = 0.0;
+}
+
+void node_tex_environment_mirror_ball(vec3 co, out vec3 uv)
+{
+ vec3 nco = normalize(co);
+ nco.y -= 1.0;
+
+ float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0));
+ nco /= max(1e-8, div);
+
+ uv = 0.5 * nco.xzz + 0.5;
+}
+
+void node_tex_environment_empty(vec3 co, out vec4 color)
+{
+ color = vec4(1.0, 0.0, 1.0, 1.0);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_gradient.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_gradient.glsl
new file mode 100644
index 00000000000..f2f7e615267
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_gradient.glsl
@@ -0,0 +1,47 @@
+float calc_gradient(vec3 p, int gradient_type)
+{
+ float x, y, z;
+ x = p.x;
+ y = p.y;
+ z = p.z;
+ if (gradient_type == 0) { /* linear */
+ return x;
+ }
+ else if (gradient_type == 1) { /* quadratic */
+ float r = max(x, 0.0);
+ return r * r;
+ }
+ else if (gradient_type == 2) { /* easing */
+ float r = min(max(x, 0.0), 1.0);
+ float t = r * r;
+ return (3.0 * t - 2.0 * t * r);
+ }
+ else if (gradient_type == 3) { /* diagonal */
+ return (x + y) * 0.5;
+ }
+ else if (gradient_type == 4) { /* radial */
+ return atan(y, x) / (M_PI * 2) + 0.5;
+ }
+ else {
+ /* Bias a little bit for the case where p is a unit length vector,
+ * to get exactly zero instead of a small random value depending
+ * on float precision. */
+ float r = max(0.999999 - sqrt(x * x + y * y + z * z), 0.0);
+ if (gradient_type == 5) { /* quadratic sphere */
+ return r * r;
+ }
+ else if (gradient_type == 6) { /* sphere */
+ return r;
+ }
+ }
+ return 0.0;
+}
+
+void node_tex_gradient(vec3 co, float gradient_type, out vec4 color, out float fac)
+{
+ float f = calc_gradient(co, int(gradient_type));
+ f = clamp(f, 0.0, 1.0);
+
+ color = vec4(f, f, f, 1.0);
+ fac = f;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
new file mode 100644
index 00000000000..c234e064d36
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
@@ -0,0 +1,355 @@
+void point_texco_remap_square(vec3 vin, out vec3 vout)
+{
+ vout = vin * 2.0 - 1.0;
+}
+
+void point_texco_clamp(vec3 vin, sampler2D ima, out vec3 vout)
+{
+ vec2 half_texel_size = 0.5 / vec2(textureSize(ima, 0).xy);
+ vout = clamp(vin, half_texel_size.xyy, 1.0 - half_texel_size.xyy);
+}
+
+void point_map_to_sphere(vec3 vin, out vec3 vout)
+{
+ float len = length(vin);
+ float v, u;
+ if (len > 0.0) {
+ if (vin.x == 0.0 && vin.y == 0.0) {
+ u = 0.0;
+ }
+ else {
+ u = (1.0 - atan(vin.x, vin.y) / M_PI) / 2.0;
+ }
+
+ v = 1.0 - acos(vin.z / len) / M_PI;
+ }
+ else {
+ v = u = 0.0;
+ }
+
+ vout = vec3(u, v, 0.0);
+}
+
+void point_map_to_tube(vec3 vin, out vec3 vout)
+{
+ float u, v;
+ v = (vin.z + 1.0) * 0.5;
+ float len = sqrt(vin.x * vin.x + vin.y * vin[1]);
+ if (len > 0.0) {
+ u = (1.0 - (atan(vin.x / len, vin.y / len) / M_PI)) * 0.5;
+ }
+ else {
+ v = u = 0.0;
+ }
+
+ vout = vec3(u, v, 0.0);
+}
+
+/* 16bits floats limits. Higher/Lower values produce +/-inf. */
+#define safe_color(a) (clamp(a, -65520.0, 65520.0))
+
+void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+{
+ color = safe_color(texture(ima, co.xy));
+ alpha = color.a;
+}
+
+void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+{
+ color = safe_color(textureLod(ima, co.xy, 0.0));
+ 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 = safe_color(texelFetch(ima, pix, 0));
+ alpha = color.a;
+}
+
+/* @arg f: signed distance to texel center. */
+void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3)
+{
+ vec2 f2 = f * f;
+ vec2 f3 = f2 * f;
+ /* Bspline coefs (optimized) */
+ w3 = f3 / 6.0;
+ w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0;
+ w1 = f3 * 0.5 - f2 * 1.0 + 2.0 / 3.0;
+ w2 = 1.0 - w0 - w1 - w3;
+}
+
+void node_tex_image_cubic_ex(
+ vec3 co, sampler2D ima, float do_extend, 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 w0, w1, w2, w3;
+ cubic_bspline_coefs(co.xy - tc, w0, w1, w2, 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;
+
+ if (do_extend == 1.0) {
+ final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5);
+ }
+ final_co /= tex_size.xyxy;
+
+ color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y;
+ color += safe_color(textureLod(ima, final_co.zy, 0.0)) * s1.x * s0.y;
+ color += safe_color(textureLod(ima, final_co.xw, 0.0)) * s0.x * s1.y;
+ color += safe_color(textureLod(ima, final_co.zw, 0.0)) * 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_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+{
+ node_tex_image_cubic_ex(co, ima, 0.0, color, alpha);
+}
+
+void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+{
+ node_tex_image_cubic_ex(co, ima, 1.0, color, alpha);
+}
+
+void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha)
+{
+ /* use cubic for now */
+ node_tex_image_cubic_ex(co, ima, 0.0, 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_ex(uv.xyy, ima, 0.0, color1, alpha);
+ /* Y projection */
+ uv = texco.xz;
+ if (N.y > 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha);
+ /* Z projection */
+ uv = texco.yx;
+ if (N.z > 0.0) {
+ uv.x = 1.0 - uv.x;
+ }
+ node_tex_image_cubic_ex(uv.xyy, ima, 0.0, 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)
+{
+ /* project from direction vector to barycentric coordinates in triangles */
+ 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,
+ * in between we blend between two textures, and in the middle we a blend
+ * between three textures.
+ *
+ * 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
+ * EDIT: Now there is only 4 if's. */
+
+ float limit = 0.5 + 0.5 * blend;
+
+ vec3 weight;
+ weight = N.xyz / (N.xyx + N.yzz);
+ weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 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.x < (1.0 - limit) * (N.y + N.z)) {
+ weight.x = 0.0;
+ weight.z = 1.0 - weight.y;
+ }
+ else if (N.y < (1.0 - limit) * (N.x + N.z)) {
+ weight.y = 0.0;
+ weight.x = 1.0 - weight.z;
+ }
+ else {
+ /* last case, we have a mix between three */
+ weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, blend);
+ }
+
+ color = weight.x * color1 + weight.y * color2 + weight.z * color3;
+ alpha = color.a;
+}
+
+void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
+{
+ vec2 tex_size = vec2(textureSize(ima, 0).xy);
+ vec2 minco = min(co.xy, 1.0 - co.xy);
+ minco = clamp(minco * tex_size + 0.5, 0.0, 1.0);
+ float fac = minco.x * minco.y;
+
+ color = mix(vec4(0.0), icolor, fac);
+ alpha = color.a;
+}
+
+void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
+{
+ vec4 minco = vec4(co.xy, 1.0 - co.xy);
+ color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor;
+ alpha = color.a;
+}
+
+void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, 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 w0, w1, w2, w3;
+ cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3);
+
+ /* TODO Optimize this part. I'm sure there is a smarter way to do that.
+ * Could do that when sampling? */
+#define CLIP_CUBIC_SAMPLE(samp, size) \
+ (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size))))
+ ivec2 itex_size = textureSize(ima, 0).xy;
+ float fac;
+ fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y;
+
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y;
+
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y;
+
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y;
+ fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y;
+#undef CLIP_CUBIC_SAMPLE
+
+ color = mix(vec4(0.0), icolor, fac);
+ alpha = color.a;
+}
+
+void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
+{
+ tex_clip_cubic(co, ima, icolor, color, alpha);
+}
+
+void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
+{
+ color = vec4(0.0);
+ alpha = 0.0;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_magic.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_magic.glsl
new file mode 100644
index 00000000000..942c507cc38
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_magic.glsl
@@ -0,0 +1,61 @@
+void node_tex_magic(
+ vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac)
+{
+ vec3 p = co * scale;
+ float x = sin((p.x + p.y + p.z) * 5.0);
+ float y = cos((-p.x + p.y - p.z) * 5.0);
+ float z = -cos((-p.x - p.y + p.z) * 5.0);
+
+ if (depth > 0) {
+ x *= distortion;
+ y *= distortion;
+ z *= distortion;
+ y = -cos(x - y + z);
+ y *= distortion;
+ if (depth > 1) {
+ x = cos(x - y - z);
+ x *= distortion;
+ if (depth > 2) {
+ z = sin(-x - y - z);
+ z *= distortion;
+ if (depth > 3) {
+ x = -cos(-x + y - z);
+ x *= distortion;
+ if (depth > 4) {
+ y = -sin(-x + y + z);
+ y *= distortion;
+ if (depth > 5) {
+ y = -cos(-x + y + z);
+ y *= distortion;
+ if (depth > 6) {
+ x = cos(x + y + z);
+ x *= distortion;
+ if (depth > 7) {
+ z = sin(x + y - z);
+ z *= distortion;
+ if (depth > 8) {
+ x = -cos(-x - y + z);
+ x *= distortion;
+ if (depth > 9) {
+ y = -sin(x - y + z);
+ y *= distortion;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (distortion != 0.0) {
+ distortion *= 2.0;
+ x /= distortion;
+ y /= distortion;
+ z /= distortion;
+ }
+
+ color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0);
+ fac = (color.x + color.y + color.z) / 3.0;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl
new file mode 100644
index 00000000000..52332c45c3d
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_musgrave.glsl
@@ -0,0 +1,208 @@
+/* Musgrave fBm
+ *
+ * H: fractal increment parameter
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ *
+ * from "Texturing and Modelling: A procedural approach"
+ */
+
+float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves)
+{
+ float rmd;
+ float value = 0.0;
+ float pwr = 1.0;
+ float pwHL = pow(lacunarity, -H);
+
+ for (int i = 0; i < int(octaves); i++) {
+ value += snoise(p) * pwr;
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd != 0.0) {
+ value += rmd * snoise(p) * pwr;
+ }
+
+ return value;
+}
+
+/* Musgrave Multifractal
+ *
+ * H: highest fractal dimension
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ */
+
+float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves)
+{
+ float rmd;
+ float value = 1.0;
+ float pwr = 1.0;
+ float pwHL = pow(lacunarity, -H);
+
+ for (int i = 0; i < int(octaves); i++) {
+ value *= (pwr * snoise(p) + 1.0);
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd != 0.0) {
+ value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */
+ }
+
+ return value;
+}
+
+/* Musgrave Heterogeneous Terrain
+ *
+ * H: fractal dimension of the roughest area
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ * offset: raises the terrain from `sea level'
+ */
+
+float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset)
+{
+ float value, increment, rmd;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL;
+
+ /* first unscaled octave of function; later octaves are scaled */
+ value = offset + snoise(p);
+ p *= lacunarity;
+
+ for (int i = 1; i < int(octaves); i++) {
+ increment = (snoise(p) + offset) * pwr * value;
+ value += increment;
+ pwr *= pwHL;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd != 0.0) {
+ increment = (snoise(p) + offset) * pwr * value;
+ value += rmd * increment;
+ }
+
+ return value;
+}
+
+/* Hybrid Additive/Multiplicative Multifractal Terrain
+ *
+ * H: fractal dimension of the roughest area
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ * offset: raises the terrain from `sea level'
+ */
+
+float noise_musgrave_hybrid_multi_fractal(
+ vec3 p, float H, float lacunarity, float octaves, float offset, float gain)
+{
+ float result, signal, weight, rmd;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL;
+
+ result = snoise(p) + offset;
+ weight = gain * result;
+ p *= lacunarity;
+
+ for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) {
+ if (weight > 1.0) {
+ weight = 1.0;
+ }
+
+ signal = (snoise(p) + offset) * pwr;
+ pwr *= pwHL;
+ result += weight * signal;
+ weight *= gain * signal;
+ p *= lacunarity;
+ }
+
+ rmd = octaves - floor(octaves);
+ if (rmd != 0.0) {
+ result += rmd * ((snoise(p) + offset) * pwr);
+ }
+
+ return result;
+}
+
+/* Ridged Multifractal Terrain
+ *
+ * H: fractal dimension of the roughest area
+ * lacunarity: gap between successive frequencies
+ * octaves: number of frequencies in the fBm
+ * offset: raises the terrain from `sea level'
+ */
+
+float noise_musgrave_ridged_multi_fractal(
+ vec3 p, float H, float lacunarity, float octaves, float offset, float gain)
+{
+ float result, signal, weight;
+ float pwHL = pow(lacunarity, -H);
+ float pwr = pwHL;
+
+ signal = offset - abs(snoise(p));
+ signal *= signal;
+ result = signal;
+ weight = 1.0;
+
+ for (int i = 1; i < int(octaves); i++) {
+ p *= lacunarity;
+ weight = clamp(signal * gain, 0.0, 1.0);
+ signal = offset - abs(snoise(p));
+ signal *= signal;
+ signal *= weight;
+ result += signal * pwr;
+ pwr *= pwHL;
+ }
+
+ return result;
+}
+
+float svm_musgrave(int type,
+ float dimension,
+ float lacunarity,
+ float octaves,
+ float offset,
+ float intensity,
+ float gain,
+ vec3 p)
+{
+ if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) {
+ return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves);
+ }
+ else if (type == 1 /* NODE_MUSGRAVE_FBM */) {
+ return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves);
+ }
+ else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) {
+ return intensity *
+ noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
+ }
+ else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) {
+ return intensity *
+ noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain);
+ }
+ else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) {
+ return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset);
+ }
+ return 0.0;
+}
+
+void node_tex_musgrave(vec3 co,
+ float scale,
+ float detail,
+ float dimension,
+ float lacunarity,
+ float offset,
+ float gain,
+ float type,
+ out vec4 color,
+ out float fac)
+{
+ fac = svm_musgrave(int(type), dimension, lacunarity, detail, offset, 1.0, gain, co *scale);
+
+ color = vec4(fac, fac, fac, 1.0);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl
new file mode 100644
index 00000000000..30e27da16e8
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_noise.glsl
@@ -0,0 +1,19 @@
+void node_tex_noise(
+ vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac)
+{
+ vec3 p = co * scale;
+ int hard = 0;
+ if (distortion != 0.0) {
+ vec3 r, offset = vec3(13.5, 13.5, 13.5);
+ r.x = noise(p + offset) * distortion;
+ r.y = noise(p) * distortion;
+ r.z = noise(p - offset) * distortion;
+ p += r;
+ }
+
+ fac = noise_turbulence(p, detail, hard);
+ color = vec4(fac,
+ noise_turbulence(vec3(p.y, p.x, p.z), detail, hard),
+ noise_turbulence(vec3(p.y, p.z, p.x), detail, hard),
+ 1);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl
new file mode 100644
index 00000000000..981d17b4283
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_sky.glsl
@@ -0,0 +1,4 @@
+void node_tex_sky(vec3 co, out vec4 color)
+{
+ color = vec4(1.0);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl
new file mode 100644
index 00000000000..018b74fd1a5
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl
@@ -0,0 +1,116 @@
+void node_tex_voronoi(vec3 co,
+ float scale,
+ float exponent,
+ float coloring,
+ float metric,
+ float feature,
+ out vec4 color,
+ out float fac)
+{
+ vec3 p = co * scale;
+ int xx, yy, zz, xi, yi, zi;
+ vec4 da = vec4(1e10);
+ vec3 pa[4] = vec3[4](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0));
+
+ xi = floor_to_int(p[0]);
+ yi = floor_to_int(p[1]);
+ zi = floor_to_int(p[2]);
+
+ for (xx = xi - 1; xx <= xi + 1; xx++) {
+ for (yy = yi - 1; yy <= yi + 1; yy++) {
+ for (zz = zi - 1; zz <= zi + 1; zz++) {
+ vec3 ip = vec3(xx, yy, zz);
+ vec3 vp = cellnoise_color(ip);
+ vec3 pd = p - (vp + ip);
+
+ float d = 0.0;
+ if (metric == 0.0) { /* SHD_VORONOI_DISTANCE 0 */
+ d = dot(pd, pd);
+ }
+ else if (metric == 1.0) { /* SHD_VORONOI_MANHATTAN 1 */
+ d = abs(pd[0]) + abs(pd[1]) + abs(pd[2]);
+ }
+ else if (metric == 2.0) { /* SHD_VORONOI_CHEBYCHEV 2 */
+ d = max(abs(pd[0]), max(abs(pd[1]), abs(pd[2])));
+ }
+ else if (metric == 3.0) { /* SHD_VORONOI_MINKOWSKI 3 */
+ d = pow(pow(abs(pd[0]), exponent) + pow(abs(pd[1]), exponent) +
+ pow(abs(pd[2]), exponent),
+ 1.0 / exponent);
+ }
+
+ vp += vec3(xx, yy, zz);
+ if (d < da[0]) {
+ da.yzw = da.xyz;
+ da[0] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = pa[0];
+ pa[0] = vp;
+ }
+ else if (d < da[1]) {
+ da.zw = da.yz;
+ da[1] = d;
+
+ pa[3] = pa[2];
+ pa[2] = pa[1];
+ pa[1] = vp;
+ }
+ else if (d < da[2]) {
+ da[3] = da[2];
+ da[2] = d;
+
+ pa[3] = pa[2];
+ pa[2] = vp;
+ }
+ else if (d < da[3]) {
+ da[3] = d;
+ pa[3] = vp;
+ }
+ }
+ }
+ }
+
+ if (coloring == 0.0) {
+ /* Intensity output */
+ if (feature == 0.0) { /* F1 */
+ fac = abs(da[0]);
+ }
+ else if (feature == 1.0) { /* F2 */
+ fac = abs(da[1]);
+ }
+ else if (feature == 2.0) { /* F3 */
+ fac = abs(da[2]);
+ }
+ else if (feature == 3.0) { /* F4 */
+ fac = abs(da[3]);
+ }
+ else if (feature == 4.0) { /* F2F1 */
+ fac = abs(da[1] - da[0]);
+ }
+ color = vec4(fac, fac, fac, 1.0);
+ }
+ else {
+ /* Color output */
+ vec3 col = vec3(fac, fac, fac);
+ if (feature == 0.0) { /* F1 */
+ col = pa[0];
+ }
+ else if (feature == 1.0) { /* F2 */
+ col = pa[1];
+ }
+ else if (feature == 2.0) { /* F3 */
+ col = pa[2];
+ }
+ else if (feature == 3.0) { /* F4 */
+ col = pa[3];
+ }
+ else if (feature == 4.0) { /* F2F1 */
+ col = abs(pa[1] - pa[0]);
+ }
+
+ color = vec4(cellnoise_color(col), 1.0);
+ fac = (color.x + color.y + color.z) * (1.0 / 3.0);
+ }
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl
new file mode 100644
index 00000000000..2196848a4ef
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_wave.glsl
@@ -0,0 +1,42 @@
+float calc_wave(
+ vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile)
+{
+ float n;
+
+ if (wave_type == 0) { /* type bands */
+ n = (p.x + p.y + p.z) * 10.0;
+ }
+ else { /* type rings */
+ n = length(p) * 20.0;
+ }
+
+ if (distortion != 0.0) {
+ n += distortion * noise_turbulence(p * detail_scale, detail, 0);
+ }
+
+ if (wave_profile == 0) { /* profile sin */
+ return 0.5 + 0.5 * sin(n);
+ }
+ else { /* profile saw */
+ n /= 2.0 * M_PI;
+ n -= int(n);
+ return (n < 0.0) ? n + 1.0 : n;
+ }
+}
+
+void node_tex_wave(vec3 co,
+ float scale,
+ float distortion,
+ float detail,
+ float detail_scale,
+ float wave_type,
+ float wave_profile,
+ out vec4 color,
+ out float fac)
+{
+ float f;
+ f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile));
+
+ color = vec4(f, f, f, 1.0);
+ fac = f;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_white_noise.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_white_noise.glsl
new file mode 100644
index 00000000000..fce511deb79
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_white_noise.glsl
@@ -0,0 +1,21 @@
+/* White Noise */
+
+void node_white_noise_1d(vec3 vector, float w, out float value)
+{
+ value = hash_float_to_float(w);
+}
+
+void node_white_noise_2d(vec3 vector, float w, out float value)
+{
+ value = hash_vec2_to_float(vector.xy);
+}
+
+void node_white_noise_3d(vec3 vector, float w, out float value)
+{
+ value = hash_vec3_to_float(vector);
+}
+
+void node_white_noise_4d(vec3 vector, float w, out float value)
+{
+ value = hash_vec4_to_float(vec4(vector, w));
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl
new file mode 100644
index 00000000000..24276156d55
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_texture_coordinates.glsl
@@ -0,0 +1,92 @@
+vec3 mtex_2d_mapping(vec3 vec)
+{
+ return vec3(vec.xy * 0.5 + vec2(0.5), vec.z);
+}
+
+void generated_from_orco(vec3 orco, out vec3 generated)
+{
+#ifdef VOLUMETRICS
+# ifdef MESH_SHADER
+ generated = volumeObjectLocalCoord;
+# else
+ generated = worldPosition;
+# endif
+#else
+ generated = orco;
+#endif
+}
+
+void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated)
+{
+ vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (ProjectionMatrixInverse * v);
+ vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+ co.xyz = normalize(co.xyz);
+#if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE)
+ generated = (ViewMatrixInverse * co).xyz;
+#else
+ generated_from_orco(attr_orco, generated);
+#endif
+}
+
+void node_tex_coord(vec3 I,
+ vec3 wN,
+ mat4 obmatinv,
+ vec4 camerafac,
+ vec3 attr_orco,
+ vec3 attr_uv,
+ out vec3 generated,
+ out vec3 normal,
+ out vec3 uv,
+ out vec3 object,
+ out vec3 camera,
+ out vec3 window,
+ out vec3 reflection)
+{
+ generated = attr_orco;
+ normal = normalize(normal_world_to_object(wN));
+ uv = attr_uv;
+ object = (obmatinv * (ViewMatrixInverse * vec4(I, 1.0))).xyz;
+ camera = vec3(I.xy, -I.z);
+ vec4 projvec = ProjectionMatrix * vec4(I, 1.0);
+ window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
+ reflection = -reflect(cameraVec, normalize(wN));
+}
+
+void node_tex_coord_background(vec3 I,
+ vec3 N,
+ mat4 obmatinv,
+ vec4 camerafac,
+ vec3 attr_orco,
+ vec3 attr_uv,
+ out vec3 generated,
+ out vec3 normal,
+ out vec3 uv,
+ out vec3 object,
+ out vec3 camera,
+ out vec3 window,
+ out vec3 reflection)
+{
+ vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
+ vec4 co_homogenous = (ProjectionMatrixInverse * v);
+
+ vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+
+ co = normalize(co);
+
+ vec3 coords = (ViewMatrixInverse * co).xyz;
+
+ generated = coords;
+ normal = -coords;
+ uv = vec3(attr_uv.xy, 0.0);
+ object = (obmatinv * vec4(coords, 1.0)).xyz;
+
+ camera = vec3(co.xy, -co.z);
+ window = vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0);
+
+ reflection = -coords;
+}
+
+#if defined(WORLD_BACKGROUND) || (defined(PROBE_CAPTURE) && !defined(MESH_SHADER))
+# define node_tex_coord node_tex_coord_background
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_toon.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_toon.glsl
new file mode 100644
index 00000000000..02d288d42bf
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_toon.glsl
@@ -0,0 +1,9 @@
+#ifndef VOLUMETRICS
+void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result)
+{
+ node_bsdf_diffuse(color, 0.0, N, result);
+}
+#else
+/* Stub toon because it is not compatible with volumetrics. */
+# define node_bsdf_toon
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
new file mode 100644
index 00000000000..ea41790e6aa
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_translucent.glsl
@@ -0,0 +1,9 @@
+#ifndef VOLUMETRICS
+void node_bsdf_translucent(vec4 color, vec3 N, out Closure result)
+{
+ node_bsdf_diffuse(color, 0.0, -N, result);
+}
+#else
+/* Stub translucent because it is not compatible with volumetrics. */
+# define node_bsdf_translucent
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_transparent.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_transparent.glsl
new file mode 100644
index 00000000000..800d0f81d4a
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_transparent.glsl
@@ -0,0 +1,11 @@
+#ifndef VOLUMETRICS
+void node_bsdf_transparent(vec4 color, out Closure result)
+{
+ result = CLOSURE_DEFAULT;
+ result.radiance = vec3(0.0);
+ result.transmittance = abs(color.rgb);
+}
+#else
+/* Stub transparent because it is not compatible with volumetrics. */
+# define node_bsdf_transparent
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_uv_map.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_uv_map.glsl
new file mode 100644
index 00000000000..d8fcbbfc361
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_uv_map.glsl
@@ -0,0 +1,4 @@
+void node_uvmap(vec3 attr_uv, out vec3 outvec)
+{
+ outvec = attr_uv;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl
new file mode 100644
index 00000000000..35d2e903cf4
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_curves.glsl
@@ -0,0 +1,8 @@
+void curves_vec(float fac, vec3 vec, sampler1DArray curvemap, float layer, out vec3 outvec)
+{
+ 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);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_displacement.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_displacement.glsl
new file mode 100644
index 00000000000..b6b955dcdb4
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_displacement.glsl
@@ -0,0 +1,30 @@
+void node_vector_displacement_tangent(vec4 vector,
+ float midlevel,
+ float scale,
+ vec4 tangent,
+ vec3 normal,
+ mat4 obmat,
+ mat4 viewmat,
+ out vec3 result)
+{
+ /* TODO(fclem) this is broken. revisit latter. */
+ vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz);
+ vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz);
+ vec3 B_object = tangent.w * normalize(cross(N_object, T_object));
+
+ vec3 offset = (vector.xyz - vec3(midlevel)) * scale;
+ result = offset.x * T_object + offset.y * N_object + offset.z * B_object;
+ result = (obmat * vec4(result, 0.0)).xyz;
+}
+
+void node_vector_displacement_object(
+ vec4 vector, float midlevel, float scale, mat4 obmat, out vec3 result)
+{
+ result = (vector.xyz - vec3(midlevel)) * scale;
+ result = (obmat * vec4(result, 0.0)).xyz;
+}
+
+void node_vector_displacement_world(vec4 vector, float midlevel, float scale, out vec3 result)
+{
+ result = (vector.xyz - vec3(midlevel)) * scale;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl
new file mode 100644
index 00000000000..93132b6044f
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_vector_math.glsl
@@ -0,0 +1,100 @@
+void vector_math_add(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = a + b;
+}
+
+void vector_math_subtract(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = a - b;
+}
+
+void vector_math_multiply(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = a * b;
+}
+
+void vector_math_divide(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = safe_divide(a, b);
+}
+
+void vector_math_cross(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = cross(a, b);
+}
+
+void vector_math_project(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ float lenSquared = dot(b, b);
+ outVector = (lenSquared != 0.0) ? (dot(a, b) / lenSquared) * b : vec3(0.0);
+}
+
+void vector_math_reflect(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = reflect(a, normalize(b));
+}
+
+void vector_math_dot(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outValue = dot(a, b);
+}
+
+void vector_math_distance(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outValue = distance(a, b);
+}
+
+void vector_math_length(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outValue = length(a);
+}
+
+void vector_math_scale(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = a * scale;
+}
+
+void vector_math_normalize(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = normalize(a);
+}
+
+void vector_math_snap(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = floor(safe_divide(a, b)) * b;
+}
+
+void vector_math_floor(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = floor(a);
+}
+
+void vector_math_ceil(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = ceil(a);
+}
+
+void vector_math_modulo(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = c_mod(a, b);
+}
+
+void vector_math_fraction(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = fract(a);
+}
+
+void vector_math_absolute(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = abs(a);
+}
+
+void vector_math_minimum(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = min(a, b);
+}
+
+void vector_math_maximum(vec3 a, vec3 b, float scale, out vec3 outVector, out float outValue)
+{
+ outVector = max(a, b);
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_velvet.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_velvet.glsl
new file mode 100644
index 00000000000..9646ffff8ca
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_velvet.glsl
@@ -0,0 +1,9 @@
+#ifndef VOLUMETRICS
+void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result)
+{
+ node_bsdf_diffuse(color, 0.0, N, result);
+}
+#else
+/* Stub velvet because it is not compatible with volumetrics. */
+# define node_bsdf_velvet
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_absorption.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_absorption.glsl
new file mode 100644
index 00000000000..e6c0880cd07
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_absorption.glsl
@@ -0,0 +1,8 @@
+void node_volume_absorption(vec4 color, float density, out Closure result)
+{
+#ifdef VOLUMETRICS
+ result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl
new file mode 100644
index 00000000000..501aeb6f34e
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_info.glsl
@@ -0,0 +1,88 @@
+void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+ outvec = texture(tex, cos).aaa;
+ outcol = vec4(outvec, 1.0);
+ outf = avg(outvec);
+}
+
+uniform vec3 volumeColor = vec3(1.0);
+
+void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+
+ vec4 value = texture(tex, cos).rgba;
+ /* Density is premultiplied for interpolation, divide it out here. */
+ if (value.a > 1e-8) {
+ value.rgb /= value.a;
+ }
+
+ outvec = value.rgb * volumeColor;
+ outcol = vec4(outvec, 1.0);
+ outf = avg(outvec);
+}
+
+void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+ outf = texture(tex, cos).r;
+ outvec = vec3(outf, outf, outf);
+ outcol = vec4(outf, outf, outf, 1.0);
+}
+
+void node_attribute_volume_temperature(
+ sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf)
+{
+#if defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 cos = volumeObjectLocalCoord;
+#else
+ vec3 cos = vec3(0.0);
+#endif
+ float flame = texture(tex, cos).r;
+
+ outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0;
+ outvec = vec3(outf, outf, outf);
+ outcol = vec4(outf, outf, outf, 1.0);
+}
+
+void node_volume_info(sampler3D densitySampler,
+ sampler3D flameSampler,
+ vec2 temperature,
+ out vec4 outColor,
+ out float outDensity,
+ out float outFlame,
+ out float outTemprature)
+{
+#if defined(MESH_SHADER) && defined(VOLUMETRICS)
+ vec3 p = volumeObjectLocalCoord;
+#else
+ vec3 p = vec3(0.0);
+#endif
+
+ vec4 density = texture(densitySampler, p);
+ outDensity = density.a;
+
+ /* Density is premultiplied for interpolation, divide it out here. */
+ if (density.a > 1e-8) {
+ density.rgb /= density.a;
+ }
+ outColor = vec4(density.rgb * volumeColor, 1.0);
+
+ float flame = texture(flameSampler, p).r;
+ outFlame = flame;
+
+ outTemprature = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0;
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl
new file mode 100644
index 00000000000..884d5415c51
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_principled.glsl
@@ -0,0 +1,67 @@
+void node_volume_principled(vec4 color,
+ float density,
+ float anisotropy,
+ vec4 absorption_color,
+ float emission_strength,
+ vec4 emission_color,
+ float blackbody_intensity,
+ vec4 blackbody_tint,
+ float temperature,
+ float density_attribute,
+ vec4 color_attribute,
+ float temperature_attribute,
+ sampler1DArray spectrummap,
+ float layer,
+ out Closure result)
+{
+#ifdef VOLUMETRICS
+ vec3 absorption_coeff = vec3(0.0);
+ vec3 scatter_coeff = vec3(0.0);
+ vec3 emission_coeff = vec3(0.0);
+
+ /* Compute density. */
+ density = max(density, 0.0);
+
+ if (density > 1e-5) {
+ density = max(density * density_attribute, 0.0);
+ }
+
+ if (density > 1e-5) {
+ /* Compute scattering and absorption coefficients. */
+ vec3 scatter_color = color.rgb * color_attribute.rgb;
+
+ scatter_coeff = scatter_color * density;
+ absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0));
+ absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) *
+ density;
+ }
+
+ /* Compute emission. */
+ emission_strength = max(emission_strength, 0.0);
+
+ if (emission_strength > 1e-5) {
+ emission_coeff += emission_strength * emission_color.rgb;
+ }
+
+ if (blackbody_intensity > 1e-3) {
+ /* Add temperature from attribute. */
+ float T = max(temperature * max(temperature_attribute, 0.0), 0.0);
+
+ /* Stefan-Boltzman law. */
+ float T2 = T * T;
+ float T4 = T2 * T2;
+ float sigma = 5.670373e-8 * 1e-6 / M_PI;
+ float intensity = sigma * mix(1.0, T4, blackbody_intensity);
+
+ if (intensity > 1e-5) {
+ vec4 bb;
+ node_blackbody(T, spectrummap, layer, bb);
+ emission_coeff += bb.rgb * blackbody_tint.rgb * intensity;
+ }
+ }
+
+ result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_volume_scatter.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_volume_scatter.glsl
new file mode 100644
index 00000000000..02c54658be5
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_volume_scatter.glsl
@@ -0,0 +1,8 @@
+void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result)
+{
+#ifdef VOLUMETRICS
+ result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy);
+#else
+ result = CLOSURE_DEFAULT;
+#endif
+}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_wireframe.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_wireframe.glsl
new file mode 100644
index 00000000000..2fcf1b8d914
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_wireframe.glsl
@@ -0,0 +1,31 @@
+#ifndef VOLUMETRICS
+void node_wireframe(float size, vec2 barycentric, vec3 barycentric_dist, out float fac)
+{
+ vec3 barys = barycentric.xyy;
+ barys.z = 1.0 - barycentric.x - barycentric.y;
+
+ size *= 0.5;
+ vec3 s = step(-size, -barys * barycentric_dist);
+
+ fac = max(s.x, max(s.y, s.z));
+}
+
+void node_wireframe_screenspace(float size, vec2 barycentric, out float fac)
+{
+ vec3 barys = barycentric.xyy;
+ barys.z = 1.0 - barycentric.x - barycentric.y;
+
+ size *= (1.0 / 3.0);
+ vec3 dx = dFdx(barys);
+ vec3 dy = dFdy(barys);
+ vec3 deltas = sqrt(dx * dx + dy * dy);
+
+ vec3 s = step(-deltas * size, -barys);
+
+ fac = max(s.x, max(s.y, s.z));
+}
+#else
+/* Stub wireframe because it is not compatible with volumetrics. */
+# define node_wireframe
+# define node_wireframe_screenspace
+#endif
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl
new file mode 100644
index 00000000000..f9691beee6f
--- /dev/null
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_world_normals.glsl
@@ -0,0 +1,25 @@
+/* TODO : clean this ifdef mess */
+void world_normals_get(out vec3 N)
+{
+#ifndef VOLUMETRICS
+# ifdef HAIR_SHADER
+ vec3 B = normalize(cross(worldNormal, hairTangent));
+ float cos_theta;
+ if (hairThicknessRes == 1) {
+ vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
+ /* Random cosine normal distribution on the hair surface. */
+ cos_theta = rand.x * 2.0 - 1.0;
+ }
+ else {
+ /* Shade as a cylinder. */
+ cos_theta = hairThickTime / hairThickness;
+ }
+ float sin_theta = sqrt(max(0.0, 1.0 - cos_theta * cos_theta));
+ N = normalize(worldNormal * sin_theta + B * cos_theta);
+# else
+ N = gl_FrontFacing ? worldNormal : -worldNormal;
+# endif
+#else
+ generated_from_orco(vec3(0.0), N);
+#endif
+}
diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp
index 883919d76ec..2ceedca59f7 100644
--- a/source/blender/ikplugin/intern/itasc_plugin.cpp
+++ b/source/blender/ikplugin/intern/itasc_plugin.cpp
@@ -879,7 +879,7 @@ static bool joint_callback(const iTaSC::Timestamp &timestamp,
bPoseChannel *chan = ikchan->pchan;
int dof;
- // a channel can be splitted into multiple joints, so we get called multiple
+ // a channel can be split into multiple joints, so we get called multiple
// times for one channel (this callback is only for 1 joint in the armature)
// the IK_JointTarget structure is shared between multiple joint constraint
// and the target joint values is computed only once, remember this in jointValid
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 791e939db7f..7e7e489a6c3 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -46,8 +46,7 @@
*
* IMB needs:
* - \ref DNA module
- * The listbase types are used for handling the memory
- * management.
+ * The #ListBase types are used for handling the memory management.
* - \ref blenlib module
* blenlib handles guarded memory management in blender-style.
* BLI_winstuff.h makes a few windows specific behaviors
@@ -146,7 +145,8 @@ bool IMB_initImBuf(
struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect,
const float *rectf,
unsigned int w,
- unsigned int h);
+ unsigned int h,
+ unsigned int channels);
/**
*
diff --git a/source/blender/imbuf/intern/allocimbuf.c b/source/blender/imbuf/intern/allocimbuf.c
index 7d2f51af65e..75db3fd3c73 100644
--- a/source/blender/imbuf/intern/allocimbuf.c
+++ b/source/blender/imbuf/intern/allocimbuf.c
@@ -428,7 +428,8 @@ bool imb_addrectImBuf(ImBuf *ibuf)
struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect,
const float *rectf,
unsigned int w,
- unsigned int h)
+ unsigned int h,
+ unsigned int channels)
{
ImBuf *ibuf = NULL;
@@ -438,6 +439,7 @@ struct ImBuf *IMB_allocFromBuffer(const unsigned int *rect,
ibuf = IMB_allocImBuf(w, h, 32, 0);
+ ibuf->channels = channels;
if (rectf) {
ibuf->rect_float = MEM_dupallocN(rectf);
ibuf->flags |= IB_rectfloat;
diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c
index 28557277d72..46ddee25b0f 100644
--- a/source/blender/imbuf/intern/scaling.c
+++ b/source/blender/imbuf/intern/scaling.c
@@ -1629,8 +1629,8 @@ bool IMB_scaleImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned int newy)
return false;
}
- /* scaleup / scaledown functions below change ibuf->x and ibuf->y
- * so we first scale the Z-buffer (if any) */
+ /* Scale-up / scale-down functions below change ibuf->x and ibuf->y
+ * so we first scale the Z-buffer (if any). */
scalefast_Z_ImBuf(ibuf, newx, newy);
/* try to scale common cases in a fast way */
diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h
index ef9069acb78..ed7416e06c9 100644
--- a/source/blender/makesdna/DNA_ID.h
+++ b/source/blender/makesdna/DNA_ID.h
@@ -467,7 +467,11 @@ typedef enum ID_Type {
/* id->flag (persitent). */
enum {
+ /* Don't delete the datablock even if unused. */
LIB_FAKEUSER = 1 << 9,
+ /* The datablock structure is a sub-object of a different one.
+ * Direct persistent references are not allowed. */
+ LIB_PRIVATE_DATA = 1 << 10,
};
/**
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index a4cd31a1357..b7834e2c7e0 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -847,8 +847,7 @@ typedef enum eSAction_Flag {
SACTION_POSEMARKERS_SHOW = (1 << 6),
/* don't draw action channels using group colors (where applicable) */
SACTION_NODRAWGCOLORS = (1 << 7),
- /* don't draw current frame number beside frame indicator */
- SACTION_NODRAWCFRANUM = (1 << 8),
+ /* SACTION_NODRAWCFRANUM = (1 << 8), DEPRECATED */
/* don't perform realtime updates */
SACTION_NOREALTIMEUPDATES = (1 << 10),
/* move markers as well as keyframes */
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 1718aabc51d..70add4c156f 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -319,6 +319,10 @@ typedef struct DriverTarget {
/** Transform channel index (for DVAR_TYPE_TRANSFORM_CHAN.)*/
short transChan;
+ /** Rotation channel calculation type. */
+ char rotation_mode;
+ char _pad[7];
+
/**
* Flags for the validity of the target
* (NOTE: these get reset every time the types change).
@@ -358,10 +362,36 @@ typedef enum eDriverTarget_TransformChannels {
DTAR_TRANSCHAN_SCALEY,
DTAR_TRANSCHAN_SCALEZ,
DTAR_TRANSCHAN_SCALE_AVG,
+ DTAR_TRANSCHAN_ROTW,
MAX_DTAR_TRANSCHAN_TYPES,
} eDriverTarget_TransformChannels;
+/* Rotation channel mode for Driver Targets */
+typedef enum eDriverTarget_RotationMode {
+ /** Automatic euler mode. */
+ DTAR_ROTMODE_AUTO = 0,
+
+ /** Explicit euler rotation modes - must sync with BLI_math_rotation.h defines. */
+ DTAR_ROTMODE_EULER_XYZ = 1,
+ DTAR_ROTMODE_EULER_XZY,
+ DTAR_ROTMODE_EULER_YXZ,
+ DTAR_ROTMODE_EULER_YZX,
+ DTAR_ROTMODE_EULER_ZXY,
+ DTAR_ROTMODE_EULER_ZYX,
+
+ DTAR_ROTMODE_QUATERNION,
+
+ /** Implements the very common Damped Track + child trick to decompose
+ * rotation into bending followed by twist around the remaining axis. */
+ DTAR_ROTMODE_SWING_TWIST_X,
+ DTAR_ROTMODE_SWING_TWIST_Y,
+ DTAR_ROTMODE_SWING_TWIST_Z,
+
+ DTAR_ROTMODE_EULER_MIN = DTAR_ROTMODE_EULER_XYZ,
+ DTAR_ROTMODE_EULER_MAX = DTAR_ROTMODE_EULER_ZYX,
+} eDriverTarget_RotationMode;
+
/* --- */
/* maximum number of driver targets per variable */
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index 93ce3d9769b..bae9c8f40ea 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -295,6 +295,8 @@ typedef struct Brush {
float crease_pinch_factor;
+ float normal_radius_factor;
+
float plane_trim;
/** Affectable height of brush (layer height for layer tool, i.e.). */
float height;
@@ -302,7 +304,6 @@ typedef struct Brush {
float texture_sample_bias;
int curve_preset;
- char _pad1[4];
/* overlay */
int texture_overlay_alpha;
@@ -395,7 +396,7 @@ typedef enum eBrushFlags {
BRUSH_LOCK_ALPHA = (1 << 14),
BRUSH_ORIGINAL_NORMAL = (1 << 15),
BRUSH_OFFSET_PRESSURE = (1 << 16),
- BRUSH_FLAG_UNUSED_17 = (1 << 17), /* cleared */
+ BRUSH_SCENE_SPACING = (1 << 17),
BRUSH_SPACE_ATTEN = (1 << 18),
BRUSH_ADAPTIVE_SPACE = (1 << 19),
BRUSH_LOCK_SIZE = (1 << 20),
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index eda52fdf14a..42d58cb34d0 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -271,7 +271,8 @@ typedef struct bTrackToConstraint {
typedef struct bRotateLikeConstraint {
struct Object *tar;
int flag;
- int reserved1;
+ char euler_order;
+ char _pad[3];
/** MAX_ID_NAME-2. */
char subtarget[64];
} bRotateLikeConstraint;
@@ -441,6 +442,13 @@ typedef struct bTransformConstraint {
/** Extrapolate motion? if 0, confine to ranges. */
char expo;
+ /** Input rotation type - uses the same values as driver targets. */
+ char from_rotation_mode;
+ /** Output euler order override. */
+ char to_euler_order;
+
+ char _pad[6];
+
/** From_min/max defines range of target transform. */
float from_min[3];
/** To map on to to_min/max range. */
@@ -715,6 +723,20 @@ typedef enum eConstraintChannel_Flags {
CONSTRAINT_CHANNEL_PROTECTED = (1 << 1),
} eConstraintChannel_Flags;
+/* Common enum for constraints that support override. */
+typedef enum eConstraint_EulerOrder {
+ /** Automatic euler mode. */
+ CONSTRAINT_EULER_AUTO = 0,
+
+ /** Explicit euler rotation modes - must sync with BLI_math_rotation.h defines. */
+ CONSTRAINT_EULER_XYZ = 1,
+ CONSTRAINT_EULER_XZY,
+ CONSTRAINT_EULER_YXZ,
+ CONSTRAINT_EULER_YZX,
+ CONSTRAINT_EULER_ZXY,
+ CONSTRAINT_EULER_ZYX,
+} eConstraint_EulerOrder;
+
/* -------------------------------------- */
/* bRotateLikeConstraint.flag */
@@ -748,6 +770,7 @@ typedef enum eCopyScale_Flags {
SIZELIKE_Z = (1 << 2),
SIZELIKE_OFFSET = (1 << 3),
SIZELIKE_MULTIPLY = (1 << 4),
+ SIZELIKE_UNIFORM = (1 << 5),
} eCopyScale_Flags;
/* bTransformConstraint.to/from */
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 5a169fe1d16..415eb03e26d 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -197,6 +197,9 @@ typedef enum CustomDataType {
/** Data types that may be defined for all mesh elements types. */
#define CD_MASK_GENERIC_DATA (CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR)
+/** Multires loop data. */
+#define CD_MASK_MULTIRES_GRIDS (CD_MASK_MDISPS | CD_GRID_PAINT_MASK)
+
typedef struct CustomData_MeshMasks {
uint64_t vmask;
uint64_t emask;
diff --git a/source/blender/makesdna/DNA_documentation.h b/source/blender/makesdna/DNA_documentation.h
index be11b3d9040..0251625292c 100644
--- a/source/blender/makesdna/DNA_documentation.h
+++ b/source/blender/makesdna/DNA_documentation.h
@@ -27,7 +27,7 @@
* blender file. There is an executable that scans all files, looking
* for struct-s to serialize (hence sdna: Struct \ref DNA). From this
* information, it builds a file with numbers that encode the format,
- * the names of variables, and the plce to look for them.
+ * the names of variables, and the place to look for them.
*
* \section dnaissues Known issues with DNA
*
diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h
index 663e4dd8e44..f934d70fcdf 100644
--- a/source/blender/makesdna/DNA_gpencil_modifier_types.h
+++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h
@@ -28,8 +28,6 @@
* (ONLY ADD NEW ITEMS AT THE END)
*/
-struct RNG;
-
typedef enum GpencilModifierType {
eGpencilModifierType_None = 0,
eGpencilModifierType_Noise = 1,
@@ -82,6 +80,8 @@ typedef struct NoiseGpencilModifierData {
GpencilModifierData modifier;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
@@ -110,12 +110,15 @@ typedef enum eNoiseGpencil_Flag {
GP_NOISE_INVERT_VGROUP = (1 << 8),
GP_NOISE_MOD_UV = (1 << 9),
GP_NOISE_INVERT_LAYERPASS = (1 << 10),
+ GP_NOISE_INVERT_MATERIAL = (1 << 11),
} eNoiseGpencil_Flag;
typedef struct SubdivGpencilModifierData {
GpencilModifierData modifier;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Custom index for passes. */
int pass_index;
/** Flags. */
@@ -131,12 +134,15 @@ typedef enum eSubdivGpencil_Flag {
GP_SUBDIV_INVERT_LAYER = (1 << 1),
GP_SUBDIV_INVERT_PASS = (1 << 2),
GP_SUBDIV_INVERT_LAYERPASS = (1 << 3),
+ GP_SUBDIV_INVERT_MATERIAL = (1 << 4),
} eSubdivGpencil_Flag;
typedef struct ThickGpencilModifierData {
GpencilModifierData modifier;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
@@ -157,6 +163,7 @@ typedef enum eThickGpencil_Flag {
GP_THICK_CUSTOM_CURVE = (1 << 3),
GP_THICK_NORMALIZE = (1 << 4),
GP_THICK_INVERT_LAYERPASS = (1 << 5),
+ GP_THICK_INVERT_MATERIAL = (1 << 6),
} eThickGpencil_Flag;
typedef struct TimeGpencilModifierData {
@@ -204,6 +211,8 @@ typedef struct TintGpencilModifierData {
GpencilModifierData modifier;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Custom index for passes. */
int pass_index;
/** Flags. */
@@ -225,12 +234,15 @@ typedef enum eTintGpencil_Flag {
GP_TINT_INVERT_LAYER = (1 << 1),
GP_TINT_INVERT_PASS = (1 << 2),
GP_TINT_INVERT_LAYERPASS = (1 << 3),
+ GP_TINT_INVERT_MATERIAL = (1 << 4),
} eTintGpencil_Flag;
typedef struct ColorGpencilModifierData {
GpencilModifierData modifier;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Custom index for passes. */
int pass_index;
/** Flags. */
@@ -250,12 +262,15 @@ typedef enum eColorGpencil_Flag {
GP_COLOR_INVERT_LAYER = (1 << 1),
GP_COLOR_INVERT_PASS = (1 << 2),
GP_COLOR_INVERT_LAYERPASS = (1 << 3),
+ GP_COLOR_INVERT_MATERIAL = (1 << 4),
} eColorGpencil_Flag;
typedef struct OpacityGpencilModifierData {
GpencilModifierData modifier;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
@@ -280,6 +295,7 @@ typedef enum eOpacityGpencil_Flag {
GP_OPACITY_INVERT_VGROUP = (1 << 2),
GP_OPACITY_CREATE_COLORS = (1 << 3),
GP_OPACITY_INVERT_LAYERPASS = (1 << 4),
+ GP_OPACITY_INVERT_MATERIAL = (1 << 5),
} eOpacityGpencil_Flag;
typedef struct ArrayGpencilModifierData {
@@ -309,6 +325,8 @@ typedef struct ArrayGpencilModifierData {
int pass_index;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Material replace (0 keep default). */
int mat_rpl;
/** Custom index for passes. */
@@ -322,6 +340,7 @@ typedef enum eArrayGpencil_Flag {
GP_ARRAY_INVERT_PASS = (1 << 3),
GP_ARRAY_KEEP_ONTOP = (1 << 4),
GP_ARRAY_INVERT_LAYERPASS = (1 << 5),
+ GP_ARRAY_INVERT_MATERIAL = (1 << 6),
} eArrayGpencil_Flag;
typedef struct BuildGpencilModifierData {
@@ -331,6 +350,9 @@ typedef struct BuildGpencilModifierData {
char layername[64];
int pass_index;
+ /** Material name. */
+ char materialname[64];
+
/** Custom index for passes. */
int layer_pass;
@@ -401,6 +423,8 @@ typedef struct LatticeGpencilModifierData {
struct Object *object;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
@@ -419,6 +443,7 @@ typedef enum eLatticeGpencil_Flag {
GP_LATTICE_INVERT_PASS = (1 << 1),
GP_LATTICE_INVERT_VGROUP = (1 << 2),
GP_LATTICE_INVERT_LAYERPASS = (1 << 3),
+ GP_LATTICE_INVERT_MATERIAL = (1 << 4),
} eLatticeGpencil_Flag;
typedef struct MirrorGpencilModifierData {
@@ -426,6 +451,8 @@ typedef struct MirrorGpencilModifierData {
struct Object *object;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Custom index for passes. */
int pass_index;
/** Flags. */
@@ -443,6 +470,7 @@ typedef enum eMirrorGpencil_Flag {
GP_MIRROR_AXIS_Y = (1 << 4),
GP_MIRROR_AXIS_Z = (1 << 5),
GP_MIRROR_INVERT_LAYERPASS = (1 << 6),
+ GP_MIRROR_INVERT_MATERIAL = (1 << 7),
} eMirrorGpencil_Flag;
typedef struct HookGpencilModifierData {
@@ -453,6 +481,8 @@ typedef struct HookGpencilModifierData {
char subtarget[64];
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
@@ -481,6 +511,7 @@ typedef enum eHookGpencil_Flag {
GP_HOOK_INVERT_VGROUP = (1 << 2),
GP_HOOK_UNIFORM_SPACE = (1 << 3),
GP_HOOK_INVERT_LAYERPASS = (1 << 4),
+ GP_HOOK_INVERT_MATERIAL = (1 << 5),
} eHookGpencil_Flag;
typedef enum eHookGpencil_Falloff {
@@ -499,6 +530,8 @@ typedef struct SimplifyGpencilModifierData {
GpencilModifierData modifier;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Custom index for passes. */
int pass_index;
/** Flags. */
@@ -522,6 +555,7 @@ typedef enum eSimplifyGpencil_Flag {
GP_SIMPLIFY_INVERT_LAYER = (1 << 0),
GP_SIMPLIFY_INVERT_PASS = (1 << 1),
GP_SIMPLIFY_INVERT_LAYERPASS = (1 << 2),
+ GP_SIMPLIFY_INVERT_MATERIAL = (1 << 3),
} eSimplifyGpencil_Flag;
typedef enum eSimplifyGpencil_Mode {
@@ -539,6 +573,8 @@ typedef struct OffsetGpencilModifierData {
GpencilModifierData modifier;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
@@ -557,12 +593,15 @@ typedef enum eOffsetGpencil_Flag {
GP_OFFSET_INVERT_PASS = (1 << 1),
GP_OFFSET_INVERT_VGROUP = (1 << 2),
GP_OFFSET_INVERT_LAYERPASS = (1 << 3),
+ GP_OFFSET_INVERT_MATERIAL = (1 << 4),
} eOffsetGpencil_Flag;
typedef struct SmoothGpencilModifierData {
GpencilModifierData modifier;
/** Layer name. */
char layername[64];
+ /** Material name. */
+ char materialname[64];
/** Optional vertexgroup name, MAX_VGROUP_NAME. */
char vgname[64];
/** Custom index for passes. */
@@ -587,6 +626,7 @@ typedef enum eSmoothGpencil_Flag {
GP_SMOOTH_INVERT_VGROUP = (1 << 5),
GP_SMOOTH_MOD_UV = (1 << 6),
GP_SMOOTH_INVERT_LAYERPASS = (1 << 7),
+ GP_SMOOTH_INVERT_MATERIAL = (1 << 4),
} eSmoothGpencil_Flag;
typedef struct ArmatureGpencilModifierData {
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index 0de7d8bdd16..58962dd9469 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -30,8 +30,6 @@
struct ARegion;
struct AnimData;
-struct CurveMapping;
-struct GHash;
struct MDeformVert;
#define GP_DEFAULT_PIX_FACTOR 1.0f
diff --git a/source/blender/makesdna/DNA_light_types.h b/source/blender/makesdna/DNA_light_types.h
index 5e881053910..82cab5d1594 100644
--- a/source/blender/makesdna/DNA_light_types.h
+++ b/source/blender/makesdna/DNA_light_types.h
@@ -34,7 +34,6 @@
struct AnimData;
struct CurveMapping;
struct Ipo;
-struct MTex;
struct bNodeTree;
typedef struct Light {
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index caa7c98335a..cb6991ce67a 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -40,7 +40,6 @@ struct MLoopCol;
struct MLoopTri;
struct MLoopUV;
struct MPoly;
-struct MTexPoly;
struct MVert;
struct Material;
struct Mesh;
@@ -270,10 +269,4 @@ enum {
#define MESH_MAX_VERTS 2000000000L
-/* this is so we can save bmesh files that load in trunk, ignoring NGons
- * will eventually be removed */
-
-/* enable this so meshes get tessfaces calculated by default */
-/* #define USE_TESSFACE_DEFAULT */
-
#endif
diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h
index f924368de1d..50402bbdc87 100644
--- a/source/blender/makesdna/DNA_meshdata_types.h
+++ b/source/blender/makesdna/DNA_meshdata_types.h
@@ -27,8 +27,6 @@
#include "DNA_customdata_types.h"
#include "DNA_listBase.h"
-struct Image;
-
/*tessellation face, see MLoop/MPoly for the real face data*/
typedef struct MFace {
unsigned int v1, v2, v3, v4;
@@ -188,10 +186,6 @@ typedef struct MVertTri {
unsigned int tri[3];
} MVertTri;
-// typedef struct MTexPoly {
-// void *_pad;
-//} MTexPoly;
-
typedef struct MLoopUV {
float uv[2];
int flag;
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 37c0065b166..5d71d33733d 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -29,8 +29,6 @@
*/
struct Mesh;
-struct Scene;
-struct Subdiv;
typedef enum ModifierType {
eModifierType_None = 0,
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 3ad857ac7b7..af66add01f3 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -113,7 +113,7 @@ typedef struct bNodeSocket {
short stack_index;
/* XXX deprecated, kept for forward compatibility */
short stack_type DNA_DEPRECATED;
- char draw_shape;
+ char display_shape;
char _pad[3];
/** Cached data from execution. */
@@ -153,11 +153,14 @@ typedef enum eNodeSocketDatatype {
} eNodeSocketDatatype;
/* socket shape */
-typedef enum eNodeSocketDrawShape {
- SOCK_DRAW_SHAPE_CIRCLE = 0,
- SOCK_DRAW_SHAPE_SQUARE = 1,
- SOCK_DRAW_SHAPE_DIAMOND = 2,
-} eNodeSocketDrawShape;
+typedef enum eNodeSocketDisplayShape {
+ SOCK_DISPLAY_SHAPE_CIRCLE = 0,
+ SOCK_DISPLAY_SHAPE_SQUARE = 1,
+ SOCK_DISPLAY_SHAPE_DIAMOND = 2,
+ SOCK_DISPLAY_SHAPE_CIRCLE_DOT = 3,
+ SOCK_DISPLAY_SHAPE_SQUARE_DOT = 4,
+ SOCK_DISPLAY_SHAPE_DIAMOND_DOT = 5,
+} eNodeSocketDisplayShape;
/* socket side (input/output) */
typedef enum eNodeSocketInOut {
@@ -1167,34 +1170,61 @@ typedef struct NodeDenoise {
/* math node clamp */
#define SHD_MATH_CLAMP 1
-/* Math node operation/ */
+/* Math node operations. */
enum {
NODE_MATH_ADD = 0,
- NODE_MATH_SUB = 1,
- NODE_MATH_MUL = 2,
+ NODE_MATH_SUBTRACT = 1,
+ NODE_MATH_MULTIPLY = 2,
NODE_MATH_DIVIDE = 3,
- NODE_MATH_SIN = 4,
- NODE_MATH_COS = 5,
- NODE_MATH_TAN = 6,
- NODE_MATH_ASIN = 7,
- NODE_MATH_ACOS = 8,
- NODE_MATH_ATAN = 9,
- NODE_MATH_POW = 10,
- NODE_MATH_LOG = 11,
- NODE_MATH_MIN = 12,
- NODE_MATH_MAX = 13,
+ NODE_MATH_SINE = 4,
+ NODE_MATH_COSINE = 5,
+ NODE_MATH_TANGENT = 6,
+ NODE_MATH_ARCSINE = 7,
+ NODE_MATH_ARCCOSINE = 8,
+ NODE_MATH_ARCTANGENT = 9,
+ NODE_MATH_POWER = 10,
+ NODE_MATH_LOGARITHM = 11,
+ NODE_MATH_MINIMUM = 12,
+ NODE_MATH_MAXIMUM = 13,
NODE_MATH_ROUND = 14,
- NODE_MATH_LESS = 15,
- NODE_MATH_GREATER = 16,
- NODE_MATH_MOD = 17,
- NODE_MATH_ABS = 18,
- NODE_MATH_ATAN2 = 19,
+ NODE_MATH_LESS_THAN = 15,
+ NODE_MATH_GREATER_THAN = 16,
+ NODE_MATH_MODULO = 17,
+ NODE_MATH_ABSOLUTE = 18,
+ NODE_MATH_ARCTAN2 = 19,
NODE_MATH_FLOOR = 20,
NODE_MATH_CEIL = 21,
- NODE_MATH_FRACT = 22,
+ NODE_MATH_FRACTION = 22,
NODE_MATH_SQRT = 23,
};
+/* Vector Math node operations. */
+enum {
+ NODE_VECTOR_MATH_ADD = 0,
+ NODE_VECTOR_MATH_SUBTRACT = 1,
+ NODE_VECTOR_MATH_MULTIPLY = 2,
+ NODE_VECTOR_MATH_DIVIDE = 3,
+
+ NODE_VECTOR_MATH_CROSS_PRODUCT = 4,
+ NODE_VECTOR_MATH_PROJECT = 5,
+ NODE_VECTOR_MATH_REFLECT = 6,
+ NODE_VECTOR_MATH_DOT_PRODUCT = 7,
+
+ NODE_VECTOR_MATH_DISTANCE = 8,
+ NODE_VECTOR_MATH_LENGTH = 9,
+ NODE_VECTOR_MATH_SCALE = 10,
+ NODE_VECTOR_MATH_NORMALIZE = 11,
+
+ NODE_VECTOR_MATH_SNAP = 12,
+ NODE_VECTOR_MATH_FLOOR = 13,
+ NODE_VECTOR_MATH_CEIL = 14,
+ NODE_VECTOR_MATH_MODULO = 15,
+ NODE_VECTOR_MATH_FRACTION = 16,
+ NODE_VECTOR_MATH_ABSOLUTE = 17,
+ NODE_VECTOR_MATH_MINIMUM = 18,
+ NODE_VECTOR_MATH_MAXIMUM = 19,
+};
+
/* mix rgb node flags */
#define SHD_MIXRGB_USE_ALPHA 1
#define SHD_MIXRGB_CLAMP 2
diff --git a/source/blender/makesdna/DNA_object_fluidsim_types.h b/source/blender/makesdna/DNA_object_fluidsim_types.h
index 40502fc27c9..4e821ad5f07 100644
--- a/source/blender/makesdna/DNA_object_fluidsim_types.h
+++ b/source/blender/makesdna/DNA_object_fluidsim_types.h
@@ -32,7 +32,6 @@ extern "C" {
#endif
struct Ipo;
-struct Mesh;
typedef struct FluidVertexVelocity {
float vel[3];
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index beff286ab40..f307fc8fc2d 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -47,7 +47,6 @@ struct Material;
struct Mesh;
struct Object;
struct PartDeflect;
-struct ParticleSystem;
struct Path;
struct RigidBodyOb;
struct SculptSession;
@@ -163,12 +162,14 @@ typedef struct Object_Runtime {
struct Mesh *mesh_eval;
/**
* Mesh structure created during object evaluation.
- * It has deforemation only modifiers applied on it.
+ * It has deformation only modifiers applied on it.
*/
struct Mesh *mesh_deform_eval;
- /* This is a mesh representation of corresponding object.
- * It created when Python calls `object.to_mesh()`. */
+ /**
+ * This is a mesh representation of corresponding object.
+ * It created when Python calls `object.to_mesh()`.
+ */
struct Mesh *object_as_temp_mesh;
/** Runtime evaluated curve-specific data, not stored in the file. */
@@ -176,11 +177,11 @@ typedef struct Object_Runtime {
/** Runtime grease pencil drawing data */
struct GpencilBatchCache *gpencil_cache;
- /** Runtime grease pencil total layers used for derived data created by modifiers */
- int tot_layers;
+ /** Runtime grease pencil total layers used for evaluated data created by modifiers */
+ int gpencil_tot_layers;
char _pad4[4];
- /** Runtime grease pencil derived data created by modifiers */
- struct bGPDframe *derived_frames;
+ /** Runtime grease pencil evaluated data created by modifiers */
+ struct bGPDframe *gpencil_evaluated_frames;
void *_pad2; /* Padding is here for win32s unconventional struct alignment rules. */
} Object_Runtime;
@@ -515,7 +516,7 @@ enum {
OB_DUPLIROT = 1 << 5,
OB_TRANSFLAG_UNUSED_6 = 1 << 6, /* cleared */
/* runtime, calculate derivedmesh for dupli before it's used */
- OB_DUPLICALCDERIVED = 1 << 7,
+ OB_TRANSFLAG_UNUSED_7 = 1 << 7, /* dirty */
OB_DUPLICOLLECTION = 1 << 8,
OB_DUPLIFACES = 1 << 9,
OB_DUPLIFACES_SCALE = 1 << 10,
@@ -619,7 +620,11 @@ enum {
/* NOTE: this was used as a proper setting in past, so nullify before using */
#define BA_TEMP_TAG (1 << 5)
-/* #define BA_FROMSET (1 << 7) */ /*UNUSED*/
+/**
+ * Even if this is is tagged for transform, this flag means it's being locked in place.
+ * Use for #SCE_XFORM_SKIP_CHILDREN.
+ */
+#define BA_TRANSFORM_LOCKED_IN_PLACE (1 << 7)
#define BA_TRANSFORM_CHILD (1 << 8) /* child of a transformed object */
#define BA_TRANSFORM_PARENT (1 << 13) /* parent of a transformed object */
@@ -698,6 +703,7 @@ enum {
OB_EMPTY_IMAGE_HIDE_ORTHOGRAPHIC = 1 << 1,
OB_EMPTY_IMAGE_HIDE_BACK = 1 << 2,
OB_EMPTY_IMAGE_HIDE_FRONT = 1 << 3,
+ OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED = 1 << 4,
};
/** #Object.empty_image_flag */
diff --git a/source/blender/makesdna/DNA_outliner_types.h b/source/blender/makesdna/DNA_outliner_types.h
index 1462d955f81..9776063f220 100644
--- a/source/blender/makesdna/DNA_outliner_types.h
+++ b/source/blender/makesdna/DNA_outliner_types.h
@@ -60,6 +60,10 @@ enum {
TSE_DRAG_INTO = (1 << 6),
TSE_DRAG_BEFORE = (1 << 7),
TSE_DRAG_AFTER = (1 << 8),
+ /* Needed because outliner-only elements can be active */
+ TSE_ACTIVE = (1 << 9),
+ /* Needed because walk selection should not activate */
+ TSE_ACTIVE_WALK = (1 << 10),
TSE_DRAG_ANY = (TSE_DRAG_INTO | TSE_DRAG_BEFORE | TSE_DRAG_AFTER),
};
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index a6544a7f950..45d80029eac 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -58,8 +58,6 @@ struct MovieClip;
struct Object;
struct Scene;
struct SceneCollection;
-struct SceneStats;
-struct Text;
struct World;
struct bGPdata;
struct bNodeTree;
@@ -1125,7 +1123,7 @@ typedef struct GP_Sculpt_Settings {
/* GP_Sculpt_Settings.flag */
typedef enum eGP_Sculpt_SettingsFlag {
/* only affect selected points */
- GP_SCULPT_SETT_FLAG_SELECT_MASK = (1 << 0),
+ GP_SCULPT_SETT_FLAG_DEPRECATED = (1 << 0),
/* apply brush to position */
GP_SCULPT_SETT_FLAG_APPLY_POSITION = (1 << 1),
/* apply brush to strength */
@@ -1142,6 +1140,16 @@ typedef enum eGP_Sculpt_SettingsFlag {
GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE = (1 << 7),
} eGP_Sculpt_SettingsFlag;
+/* GP_Sculpt_Settings.gpencil_selectmode_sculpt */
+typedef enum eGP_Sculpt_SelectMaskFlag {
+ /* only affect selected points */
+ GP_SCULPT_MASK_SELECTMODE_POINT = (1 << 0),
+ /* only affect selected strokes */
+ GP_SCULPT_MASK_SELECTMODE_STROKE = (1 << 1),
+ /* only affect selected segmenst */
+ GP_SCULPT_MASK_SELECTMODE_SEGMENT = (1 << 2),
+} eGP_Sculpt_SelectMaskFlag;
+
/* Settings for GP Interpolation Operators */
typedef struct GP_Interpolate_Settings {
/** #eGP_Interpolate_SettingsFlag. */
@@ -1358,6 +1366,12 @@ typedef struct MeshStatVis {
/* *************************************************************** */
/* Tool Settings */
+/* CurvePaintSettings.surface_plane */
+enum {
+ AUTO_MERGE = 1 << 0,
+ AUTO_MERGE_AND_SPLIT = 1 << 1,
+};
+
typedef struct ToolSettings {
/** Vertex paint. */
VPaint *vpaint;
@@ -1412,8 +1426,10 @@ typedef struct ToolSettings {
/** Default stroke thickness for annotation strokes. */
short annotate_thickness;
- /** Stroke selection mode. */
- short gpencil_selectmode;
+ /** Stroke selection mode for Edit. */
+ char gpencil_selectmode_edit;
+ /** Stroke selection mode for Sculpt. */
+ char gpencil_selectmode_sculpt;
/* Grease Pencil Sculpt */
struct GP_Sculpt_Settings gp_sculpt;
@@ -2072,6 +2088,8 @@ extern const char *RE_engine_id_CYCLES;
(((workspace)->object_mode & OD_MODE_EDIT) ? OBACT(_view_layer) : NULL)
#define OBEDIT_FROM_OBACT(ob) ((ob) ? (((ob)->mode & OB_MODE_EDIT) ? ob : NULL) : NULL)
#define OBPOSE_FROM_OBACT(ob) ((ob) ? (((ob)->mode & OB_MODE_POSE) ? ob : NULL) : NULL)
+#define OBWEIGHTPAINT_FROM_OBACT(ob) \
+ ((ob) ? (((ob)->mode & OB_MODE_WEIGHT_PAINT) ? ob : NULL) : NULL)
#define OBEDIT_FROM_VIEW_LAYER(view_layer) OBEDIT_FROM_OBACT(OBACT(view_layer))
#define V3D_CAMERA_LOCAL(v3d) ((!(v3d)->scenelock && (v3d)->camera) ? (v3d)->camera : NULL)
@@ -2094,6 +2112,8 @@ extern const char *RE_engine_id_CYCLES;
/* ToolSettings.transform_flag */
enum {
SCE_XFORM_AXIS_ALIGN = (1 << 0),
+ SCE_XFORM_DATA_ORIGIN = (1 << 1),
+ SCE_XFORM_SKIP_CHILDREN = (1 << 2),
};
/* ToolSettings.object_flag */
@@ -2121,11 +2141,15 @@ enum {
#define SCE_SNAP_MODE_FACE (1 << 2)
#define SCE_SNAP_MODE_VOLUME (1 << 3)
#define SCE_SNAP_MODE_INCREMENT (1 << 4)
+#define SCE_SNAP_MODE_EDGE_MIDPOINT (1 << 5)
+#define SCE_SNAP_MODE_EDGE_PERPENDICULAR (1 << 6)
/* ToolSettings.snap_node_mode */
-#define SCE_SNAP_MODE_GRID (1 << 5)
-#define SCE_SNAP_MODE_NODE_X (1 << 6)
-#define SCE_SNAP_MODE_NODE_Y (1 << 7)
+#define SCE_SNAP_MODE_NODE_X (1 << 5)
+#define SCE_SNAP_MODE_NODE_Y (1 << 6)
+
+/* ToolSettings.snap_mode and ToolSettings.snap_node_mode */
+#define SCE_SNAP_MODE_GRID (1 << 7)
/** #ToolSettings.snap_transform_mode_flag */
enum {
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 5240de4aff9..087d30ce312 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -584,7 +584,7 @@ enum {
SEQ_TYPE_LIGHTEN = 44,
SEQ_TYPE_DODGE = 45,
SEQ_TYPE_DARKEN = 46,
- SEQ_TYPE_BURN = 47,
+ SEQ_TYPE_COLOR_BURN = 47,
SEQ_TYPE_LINEAR_BURN = 48,
SEQ_TYPE_OVERLAY = 49,
SEQ_TYPE_HARD_LIGHT = 50,
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 2a6a771bbeb..498ab290f31 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -246,7 +246,12 @@ typedef struct SpaceOutliner {
char search_string[64];
struct TreeStoreElem search_tse;
- short flag, outlinevis, storeflag, search_flags;
+ short flag, outlinevis, storeflag;
+ char search_flags;
+
+ /** Selection syncing flag (#WM_OUTLINER_SYNC_SELECT_FROM_OBJECT and similar flags). */
+ char sync_select_dirty;
+
int filter;
char filter_state;
char show_restrict_flags;
@@ -265,6 +270,7 @@ typedef enum eSpaceOutliner_Flag {
SO_FLAG_UNUSED_1 = (1 << 2), /* cleared */
SO_HIDE_KEYINGSETINFO = (1 << 3),
SO_SKIP_SORT_ALPHA = (1 << 4),
+ SO_SYNC_SELECT = (1 << 5),
} eSpaceOutliner_Flag;
/* SpaceOutliner.filter */
@@ -285,11 +291,12 @@ typedef enum eSpaceOutliner_Filter {
SO_FILTER_UNUSED_12 = (1 << 12), /* cleared */
SO_FILTER_OB_STATE_VISIBLE = (1 << 13), /* Not set via DNA. */
- SO_FILTER_OB_STATE_SELECTED = (1 << 14), /* Not set via DNA. */
- SO_FILTER_OB_STATE_ACTIVE = (1 << 15), /* Not set via DNA. */
- SO_FILTER_NO_COLLECTION = (1 << 16),
+ SO_FILTER_OB_STATE_HIDDEN = (1 << 14), /* Not set via DNA. */
+ SO_FILTER_OB_STATE_SELECTED = (1 << 15), /* Not set via DNA. */
+ SO_FILTER_OB_STATE_ACTIVE = (1 << 16), /* Not set via DNA. */
+ SO_FILTER_NO_COLLECTION = (1 << 17),
- SO_FILTER_ID_TYPE = (1 << 17),
+ SO_FILTER_ID_TYPE = (1 << 18),
} eSpaceOutliner_Filter;
#define SO_FILTER_OB_TYPE \
@@ -297,7 +304,8 @@ typedef enum eSpaceOutliner_Filter {
SO_FILTER_NO_OB_LAMP | SO_FILTER_NO_OB_CAMERA | SO_FILTER_NO_OB_OTHERS)
#define SO_FILTER_OB_STATE \
- (SO_FILTER_OB_STATE_VISIBLE | SO_FILTER_OB_STATE_SELECTED | SO_FILTER_OB_STATE_ACTIVE)
+ (SO_FILTER_OB_STATE_VISIBLE | SO_FILTER_OB_STATE_HIDDEN | SO_FILTER_OB_STATE_SELECTED | \
+ SO_FILTER_OB_STATE_ACTIVE)
#define SO_FILTER_ANY \
(SO_FILTER_NO_OB_CONTENT | SO_FILTER_NO_CHILDREN | SO_FILTER_OB_TYPE | SO_FILTER_OB_STATE | \
@@ -307,8 +315,9 @@ typedef enum eSpaceOutliner_Filter {
typedef enum eSpaceOutliner_StateFilter {
SO_FILTER_OB_ALL = 0,
SO_FILTER_OB_VISIBLE = 1,
- SO_FILTER_OB_SELECTED = 2,
- SO_FILTER_OB_ACTIVE = 3,
+ SO_FILTER_OB_HIDDEN = 2,
+ SO_FILTER_OB_SELECTED = 3,
+ SO_FILTER_OB_ACTIVE = 4,
} eSpaceOutliner_StateFilter;
/* SpaceOutliner.show_restrict_flags */
@@ -420,8 +429,7 @@ typedef enum eGraphEdit_Flag {
SIPO_NOTRANSKEYCULL = (1 << 1),
/* don't show any keyframe handles at all */
SIPO_NOHANDLES = (1 << 2),
- /* don't show current frame number beside indicator line */
- SIPO_NODRAWCFRANUM = (1 << 3),
+ /* SIPO_NODRAWCFRANUM = (1 << 3), DEPRECATED */
/* show timing in seconds instead of frames */
SIPO_DRAWTIME = (1 << 4),
/* only show keyframes for selected F-Curves */
@@ -496,8 +504,7 @@ typedef enum eSpaceNla_Flag {
/* draw timing in seconds instead of frames */
SNLA_DRAWTIME = (1 << 2),
SNLA_FLAG_UNUSED_3 = (1 << 3),
- /* don't draw frame number beside frame indicator */
- SNLA_NODRAWCFRANUM = (1 << 4),
+ /* SNLA_NODRAWCFRANUM = (1 << 4), DEPRECATED */
/* don't draw influence curves on strips */
SNLA_NOSTRIPCURVES = (1 << 5),
/* don't perform realtime updates */
@@ -581,7 +588,7 @@ typedef enum eSpaceSeq_Flag {
SEQ_DRAW_COLOR_SEPARATED = (1 << 2),
SEQ_SHOW_SAFE_MARGINS = (1 << 3),
SEQ_SHOW_GPENCIL = (1 << 4),
- SEQ_NO_DRAW_CFRANUM = (1 << 5),
+ /* SEQ_NO_DRAW_CFRANUM = (1 << 5), DEPRECATED */
SEQ_USE_ALPHA = (1 << 6), /* use RGBA display mode for preview */
SEQ_ALL_WAVEFORMS = (1 << 7), /* draw all waveforms */
SEQ_NO_WAVEFORMS = (1 << 8), /* draw no waveforms */
@@ -672,8 +679,11 @@ typedef struct FileSelectParams {
/** Display mode flag. */
short display;
short display_previous;
+ /** Details toggles (file size, creation date, etc.) */
+ char details_flags;
+ /* The type of file action (opening or saving) */
+ char action_type; /* eFileSel_Action */
/** Filter when (flags & FILE_FILTER) is true. */
- char _pad2[2];
int filter;
/** Max number of levels in dirtree to show at once, 0 to disable recursion. */
@@ -731,8 +741,8 @@ typedef struct SpaceFile {
/* FileSelectParams.display */
enum eFileDisplayType {
FILE_DEFAULTDISPLAY = 0,
- FILE_SHORTDISPLAY = 1,
- FILE_LONGDISPLAY = 2,
+ FILE_VERTICALDISPLAY = 1,
+ FILE_HORIZONTALDISPLAY = 2,
FILE_IMGDISPLAY = 3,
};
@@ -745,6 +755,12 @@ enum eFileSortType {
FILE_SORT_SIZE = 4,
};
+/* FileSelectParams.details_flags */
+enum eFileDetails {
+ FILE_DETAILS_SIZE = (1 << 0),
+ FILE_DETAILS_DATETIME = (1 << 1),
+};
+
/* these values need to be hardcoded in structs, dna does not recognize defines */
/* also defined in BKE */
#define FILE_MAXDIR 768
@@ -782,6 +798,8 @@ typedef enum eFileSel_Params_Flag {
FILE_FILTER = (1 << 8),
FILE_PARAMS_FLAG_UNUSED_9 = (1 << 9), /* cleared */
FILE_GROUP_INSTANCE = (1 << 10),
+ FILE_SORT_INVERT = (1 << 11),
+ FILE_HIDE_TOOL_PROPS = (1 << 12)
} eFileSel_Params_Flag;
/* sfile->params->rename_flag */
@@ -819,6 +837,8 @@ typedef enum eFileSel_File_Types {
FILE_TYPE_OPERATOR = (1 << 14),
FILE_TYPE_APPLICATIONBUNDLE = (1 << 15),
FILE_TYPE_ALEMBIC = (1 << 16),
+ /** For all kinds of recognized import/export formats. No need for specialized types. */
+ FILE_TYPE_OBJECT_IO = (1 << 17),
/** An FS directory (i.e. S_ISDIR on its path is true). */
FILE_TYPE_DIR = (1 << 30),
@@ -877,8 +897,7 @@ typedef struct FileDirEntryRevision {
int64_t time;
/* Temp caching of UI-generated strings... */
char size_str[16];
- char time_str[8];
- char date_str[16];
+ char datetime_str[16 + 8];
} FileDirEntryRevision;
/* Container for a variant, only relevant in asset context.
@@ -1113,8 +1132,6 @@ typedef enum eSpaceImage_Flag {
SI_SHOW_R = (1 << 27),
SI_SHOW_G = (1 << 28),
SI_SHOW_B = (1 << 29),
-
- SI_NO_DRAWEDGES = (1 << 30),
} eSpaceImage_Flag;
/* SpaceImage.other_uv_filter */
diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h
index 3fad1c57427..ead1bcc943d 100644
--- a/source/blender/makesdna/DNA_texture_types.h
+++ b/source/blender/makesdna/DNA_texture_types.h
@@ -35,7 +35,6 @@ extern "C" {
struct AnimData;
struct ColorBand;
struct CurveMapping;
-struct ImBuf;
struct Image;
struct Ipo;
struct Object;
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index b8914c7a74f..8eabbc0df0d 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -717,7 +717,7 @@ typedef struct UserDef {
/** Overall sensitivity of 3D mouse. */
float ndof_sensitivity;
float ndof_orbit_sensitivity;
- /** Deadzone of 3D mouse. */
+ /** Dead-zone of 3D mouse. */
float ndof_deadzone;
/** #eNdof_Flag, flags for 3D mouse. */
int ndof_flag;
@@ -868,6 +868,7 @@ typedef enum eUserPref_Flag {
USER_NONEGFRAMES = (1 << 24),
USER_TXT_TABSTOSPACES_DISABLE = (1 << 25),
USER_TOOLTIPS_PYTHON = (1 << 26),
+ USER_ADDONS_ENABLED_ONLY = (1 << 27),
} eUserPref_Flag;
typedef enum eUserPref_PrefFlag {
diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h
index 3ba33cfe3d4..51655790fbd 100644
--- a/source/blender/makesdna/DNA_view3d_types.h
+++ b/source/blender/makesdna/DNA_view3d_types.h
@@ -25,11 +25,6 @@
#define __DNA_VIEW3D_TYPES_H__
struct BoundBox;
-struct GPUViewport;
-struct Image;
-struct Material;
-struct MovieClip;
-struct MovieClipUser;
struct Object;
struct RenderEngine;
struct SmoothView3DStore;
diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h
index 8dcae41aaa2..57c0a29382d 100644
--- a/source/blender/makesdna/DNA_windowmanager_types.h
+++ b/source/blender/makesdna/DNA_windowmanager_types.h
@@ -48,7 +48,6 @@ struct PointerRNA;
struct Report;
struct ReportList;
struct Stereo3dFormat;
-struct UndoStep;
struct bContext;
struct bScreen;
struct uiLayout;
@@ -131,12 +130,15 @@ typedef struct wmWindowManager {
ListBase windows;
/** Set on file read. */
- int initialized;
+ short initialized;
/** Indicator whether data was saved. */
short file_saved;
/** Operator stack depth to avoid nested undo pushes. */
short op_undo_depth;
+ /** Set after selection to notify outliner to sync. Stores type of selection */
+ short outliner_sync_select_dirty;
+
/** Operator registry. */
ListBase operators;
@@ -186,6 +188,18 @@ enum {
WM_KEYCONFIG_IS_INITIALIZED = (1 << 1),
};
+/* wmWindowManager.outliner_sync_select_dirty */
+enum {
+ WM_OUTLINER_SYNC_SELECT_FROM_OBJECT = (1 << 0),
+ WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE = (1 << 1),
+ WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE = (1 << 2),
+ WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE = (1 << 3),
+};
+
+#define WM_OUTLINER_SYNC_SELECT_FROM_ALL \
+ (WM_OUTLINER_SYNC_SELECT_FROM_OBJECT | WM_OUTLINER_SYNC_SELECT_FROM_EDIT_BONE | \
+ WM_OUTLINER_SYNC_SELECT_FROM_POSE_BONE | WM_OUTLINER_SYNC_SELECT_FROM_SEQUENCE)
+
#define WM_KEYCONFIG_STR_DEFAULT "blender"
/* IME is win32 only! */
diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h
index 5143f667083..af1e5123dc8 100644
--- a/source/blender/makesdna/DNA_world_types.h
+++ b/source/blender/makesdna/DNA_world_types.h
@@ -29,7 +29,6 @@
struct AnimData;
struct Ipo;
-struct MTex;
struct bNodeTree;
#ifndef MAX_MTEX
diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c
index 5252c8f3350..09a7a157996 100644
--- a/source/blender/makesdna/intern/dna_genfile.c
+++ b/source/blender/makesdna/intern/dna_genfile.c
@@ -339,7 +339,7 @@ static bool init_structDNA(SDNA *sdna, bool do_endian_swap, const char **r_error
data = (int *)sdna->data;
- /* clear pointers incase of error */
+ /* Clear pointers in case of error. */
sdna->names = NULL;
sdna->types = NULL;
sdna->structs = NULL;
@@ -1102,7 +1102,7 @@ static void reconstruct_elem(const SDNA *newsdna,
* - cast type
* - name partially equal (array differs)
* - type equal: memcpy
- * - types casten
+ * - type cast (per element).
* (nzc 2-4-2001 I want the 'unsigned' bit to be parsed as well. Where
* can I force this?)
*/
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 613df728dc9..0b60d1fa344 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -1158,24 +1158,37 @@ struct PropertyElemRNA {
};
bool RNA_path_resolve_elements(PointerRNA *ptr, const char *path, struct ListBase *r_elements);
+struct ID *RNA_find_real_ID_and_path(struct Main *bmain, struct ID *id, const char **r_path);
+
char *RNA_path_from_ID_to_struct(PointerRNA *ptr);
+
+char *RNA_path_from_real_ID_to_struct(struct Main *bmain, PointerRNA *ptr, struct ID **r_real);
+
char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop);
char *RNA_path_from_ID_to_property_index(PointerRNA *ptr,
PropertyRNA *prop,
int array_dim,
int index);
+char *RNA_path_from_real_ID_to_property_index(struct Main *bmain,
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ int array_dim,
+ int index,
+ struct ID **r_real_id);
+
char *RNA_path_resolve_from_type_to_property(struct PointerRNA *ptr,
struct PropertyRNA *prop,
const struct StructRNA *type);
-char *RNA_path_full_ID_py(struct ID *id);
-char *RNA_path_full_struct_py(struct PointerRNA *ptr);
-char *RNA_path_full_property_py_ex(PointerRNA *ptr,
- PropertyRNA *prop,
- int index,
- bool use_fallback);
-char *RNA_path_full_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
+char *RNA_path_full_ID_py(struct Main *bmain, struct ID *id);
+char *RNA_path_full_struct_py(struct Main *bmain, struct PointerRNA *ptr);
+char *RNA_path_full_property_py_ex(
+ struct Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback);
+char *RNA_path_full_property_py(struct Main *bmain,
+ struct PointerRNA *ptr,
+ struct PropertyRNA *prop,
+ int index);
char *RNA_path_struct_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
char *RNA_path_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int index);
@@ -1418,8 +1431,8 @@ StructRNA *ID_code_to_RNA_type(short idcode);
#define RNA_POINTER_INVALIDATE(ptr) \
{ \
/* this is checked for validity */ \
- (ptr)->type = /* should not be needed but prevent bad pointer access, just in case */ \
- (ptr)->id.data = NULL; \
+ (ptr)->type = NULL; /* should not be needed but prevent bad pointer access, just in case */ \
+ (ptr)->owner_id = NULL; \
} \
(void)0
@@ -1511,8 +1524,8 @@ bool RNA_struct_override_store(struct Main *bmain,
struct IDOverrideLibrary *override);
void RNA_struct_override_apply(struct Main *bmain,
- struct PointerRNA *ptr_local,
- struct PointerRNA *ptr_override,
+ struct PointerRNA *ptr_dst,
+ struct PointerRNA *ptr_src,
struct PointerRNA *ptr_storage,
struct IDOverrideLibrary *override);
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 02aaef44a1f..b3e1f22f413 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -91,6 +91,7 @@ extern const EnumPropertyItem rna_enum_beztriple_keyframe_type_items[];
extern const EnumPropertyItem rna_enum_beztriple_interpolation_mode_items[];
extern const EnumPropertyItem rna_enum_beztriple_interpolation_easing_items[];
extern const EnumPropertyItem rna_enum_keyframe_handle_type_items[];
+extern const EnumPropertyItem rna_enum_driver_target_rotation_mode_items[];
extern const EnumPropertyItem rna_enum_keyblock_type_items[];
diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h
index 38631d1acf2..2a341249247 100644
--- a/source/blender/makesrna/RNA_types.h
+++ b/source/blender/makesrna/RNA_types.h
@@ -29,6 +29,7 @@ extern "C" {
struct BlenderRNA;
struct FunctionRNA;
+struct ID;
struct Main;
struct ParameterList;
struct PropertyRNA;
@@ -44,10 +45,7 @@ struct bContext;
* the properties and validate them. */
typedef struct PointerRNA {
- struct {
- void *data;
- } id;
-
+ struct ID *owner_id;
struct StructRNA *type;
void *data;
} PointerRNA;
@@ -534,7 +532,7 @@ typedef struct ParameterDynAlloc {
typedef enum FunctionFlag {
/**
* Pass ID owning 'self' data
- * (i.e. ptr->id.data, might be same as self in case data is an ID...).
+ * (i.e. ptr->owner_id, might be same as self in case data is an ID...).
*/
FUNC_USE_SELF_ID = (1 << 11),
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index ab13c6c9ed4..05408f1a41a 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -365,9 +365,11 @@ add_custom_command(
# Build bf_rna
set(SRC
rna_access.c
+ rna_access_compare_override.c
${GENSRC}
${SRC_RNA_INC}
+ rna_access_internal.h
rna_internal.h
rna_internal_types.h
rna_mesh_utils.h
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index f6c248acdb5..1617d85b6c2 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -389,7 +389,7 @@ static void rna_print_data_get(FILE *f, PropertyDefRNA *dp)
static void rna_print_id_get(FILE *f, PropertyDefRNA *UNUSED(dp))
{
- fprintf(f, " ID *id = ptr->id.data;\n");
+ fprintf(f, " ID *id = ptr->owner_id;\n");
}
static void rna_construct_function_name(
@@ -2470,7 +2470,7 @@ static void rna_def_struct_function_call_impl_cpp(FILE *f, StructRNA *srna, Func
dsrna = rna_find_struct_def(srna);
if (func->flag & FUNC_USE_SELF_ID) {
- WRITE_PARAM("(::ID *) ptr.id.data");
+ WRITE_PARAM("(::ID *) ptr.owner_id");
}
if ((func->flag & FUNC_NO_SELF) == 0) {
@@ -2579,7 +2579,7 @@ static void rna_def_struct_function_impl_cpp(FILE *f, StructRNA *srna, FunctionD
}
else {
fprintf(f,
- "\t\tRNA_pointer_create((::ID *) ptr.id.data, &RNA_%s, retdata, &result);\n",
+ "\t\tRNA_pointer_create((::ID *) ptr.owner_id, &RNA_%s, retdata, &result);\n",
(const char *)pprop->type);
}
}
@@ -2792,7 +2792,7 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA
/* assign self */
if (func->flag & FUNC_USE_SELF_ID) {
- fprintf(f, "\t_selfid = (struct ID *)_ptr->id.data;\n");
+ fprintf(f, "\t_selfid = (struct ID *)_ptr->owner_id;\n");
}
if ((func->flag & FUNC_NO_SELF) == 0) {
diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c
index 57cdbbadeb8..5a4b4a3fa3d 100644
--- a/source/blender/makesrna/intern/rna_ID.c
+++ b/source/blender/makesrna/intern/rna_ID.c
@@ -620,9 +620,9 @@ static int rna_IDPArray_length(PointerRNA *ptr)
int rna_IDMaterials_assign_int(PointerRNA *ptr, int key, const PointerRNA *assign_ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
short *totcol = give_totcolp_id(id);
- Material *mat_id = assign_ptr->id.data;
+ Material *mat_id = (Material *)assign_ptr->owner_id;
if (totcol && (key >= 0 && key < *totcol)) {
BLI_assert(BKE_id_is_in_global_main(id));
BLI_assert(BKE_id_is_in_global_main(&mat_id->id));
@@ -642,8 +642,7 @@ static void rna_IDMaterials_append_id(ID *id, Main *bmain, Material *ma)
WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, id);
}
-static Material *rna_IDMaterials_pop_id(
- ID *id, Main *bmain, ReportList *reports, int index_i, bool remove_material_slot)
+static Material *rna_IDMaterials_pop_id(ID *id, Main *bmain, ReportList *reports, int index_i)
{
Material *ma;
short *totcol = give_totcolp_id(id);
@@ -657,7 +656,7 @@ static Material *rna_IDMaterials_pop_id(
return NULL;
}
- ma = BKE_material_pop_id(bmain, id, index_i, remove_material_slot);
+ ma = BKE_material_pop_id(bmain, id, index_i);
if (*totcol == totcol_orig) {
BKE_report(reports, RPT_ERROR, "No material to removed");
@@ -671,9 +670,9 @@ static Material *rna_IDMaterials_pop_id(
return ma;
}
-static void rna_IDMaterials_clear_id(ID *id, Main *bmain, bool remove_material_slot)
+static void rna_IDMaterials_clear_id(ID *id, Main *bmain)
{
- BKE_material_clear_id(bmain, id, remove_material_slot);
+ BKE_material_clear_id(bmain, id);
DEG_id_tag_update(id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, id);
@@ -691,7 +690,7 @@ static void rna_Library_filepath_set(PointerRNA *ptr, const char *value)
static void rna_ImagePreview_is_custom_set(PointerRNA *ptr, int value, enum eIconSizes size)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
PreviewImage *prv_img = (PreviewImage *)ptr->data;
if (id != NULL) {
@@ -717,7 +716,7 @@ static void rna_ImagePreview_is_custom_set(PointerRNA *ptr, int value, enum eIco
static void rna_ImagePreview_size_get(PointerRNA *ptr, int *values, enum eIconSizes size)
{
- ID *id = (ID *)ptr->id.data;
+ ID *id = ptr->owner_id;
PreviewImage *prv_img = (PreviewImage *)ptr->data;
if (id != NULL) {
@@ -732,7 +731,7 @@ static void rna_ImagePreview_size_get(PointerRNA *ptr, int *values, enum eIconSi
static void rna_ImagePreview_size_set(PointerRNA *ptr, const int *values, enum eIconSizes size)
{
- ID *id = (ID *)ptr->id.data;
+ ID *id = ptr->owner_id;
PreviewImage *prv_img = (PreviewImage *)ptr->data;
if (id != NULL) {
@@ -755,7 +754,7 @@ static int rna_ImagePreview_pixels_get_length(PointerRNA *ptr,
int length[RNA_MAX_ARRAY_DIMENSION],
enum eIconSizes size)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
PreviewImage *prv_img = (PreviewImage *)ptr->data;
if (id != NULL) {
@@ -771,7 +770,7 @@ static int rna_ImagePreview_pixels_get_length(PointerRNA *ptr,
static void rna_ImagePreview_pixels_get(PointerRNA *ptr, int *values, enum eIconSizes size)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
PreviewImage *prv_img = (PreviewImage *)ptr->data;
if (id != NULL) {
@@ -785,7 +784,7 @@ static void rna_ImagePreview_pixels_get(PointerRNA *ptr, int *values, enum eIcon
static void rna_ImagePreview_pixels_set(PointerRNA *ptr, const int *values, enum eIconSizes size)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
PreviewImage *prv_img = (PreviewImage *)ptr->data;
if (id != NULL) {
@@ -800,7 +799,7 @@ static int rna_ImagePreview_pixels_float_get_length(PointerRNA *ptr,
int length[RNA_MAX_ARRAY_DIMENSION],
enum eIconSizes size)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
PreviewImage *prv_img = (PreviewImage *)ptr->data;
BLI_assert(sizeof(unsigned int) == 4);
@@ -818,7 +817,7 @@ static int rna_ImagePreview_pixels_float_get_length(PointerRNA *ptr,
static void rna_ImagePreview_pixels_float_get(PointerRNA *ptr, float *values, enum eIconSizes size)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
PreviewImage *prv_img = (PreviewImage *)ptr->data;
unsigned char *data = (unsigned char *)prv_img->rect[size];
@@ -842,7 +841,7 @@ static void rna_ImagePreview_pixels_float_set(PointerRNA *ptr,
const float *values,
enum eIconSizes size)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
PreviewImage *prv_img = (PreviewImage *)ptr->data;
unsigned char *data = (unsigned char *)prv_img->rect[size];
@@ -959,7 +958,7 @@ static int rna_ImagePreview_icon_id_get(PointerRNA *ptr)
{
/* Using a callback here allows us to only generate icon matching
* that preview when icon_id is requested. */
- return BKE_icon_preview_ensure(ptr->id.data, (PreviewImage *)(ptr->data));
+ return BKE_icon_preview_ensure(ptr->owner_id, (PreviewImage *)(ptr->data));
}
static void rna_ImagePreview_icon_reload(PreviewImage *prv)
{
@@ -1116,16 +1115,12 @@ static void rna_def_ID_materials(BlenderRNA *brna)
RNA_def_function_ui_description(func, "Remove a material from the data-block");
parm = RNA_def_int(
func, "index", -1, -MAXMAT, MAXMAT, "", "Index of material to remove", 0, MAXMAT);
- RNA_def_boolean(
- func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned");
parm = RNA_def_pointer(func, "material", "Material", "", "Material to remove");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "clear", "rna_IDMaterials_clear_id");
RNA_def_function_flag(func, FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Remove all materials from the data-block");
- RNA_def_boolean(
- func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned");
}
static void rna_def_image_preview(BlenderRNA *brna)
@@ -1455,6 +1450,7 @@ static void rna_def_ID(BlenderRNA *brna)
"Actual data-block from .blend file (Main database) that generated that evaluated one");
RNA_def_property_pointer_funcs(prop, "rna_ID_original_get", NULL, NULL, NULL);
RNA_def_property_clear_flag(prop, PROP_EDITABLE | PROP_PTR_NO_OWNERSHIP);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
prop = RNA_def_property(srna, "users", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "us");
@@ -1483,6 +1479,7 @@ static void rna_def_ID(BlenderRNA *brna)
prop = RNA_def_property(srna, "library", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "lib");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
RNA_def_property_ui_text(prop, "Library", "Library file the data-block is linked from");
prop = RNA_def_pointer(
@@ -1607,6 +1604,7 @@ static void rna_def_library(BlenderRNA *brna)
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Library");
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
RNA_def_property_ui_text(prop, "Parent", "");
prop = RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c
index 330d45c2fa5..61634a84d41 100644
--- a/source/blender/makesrna/intern/rna_access.c
+++ b/source/blender/makesrna/intern/rna_access.c
@@ -37,21 +37,18 @@
#include "BLI_ghash.h"
#include "BLI_math.h"
-#ifdef DEBUG_OVERRIDE_TIMEIT
-# include "PIL_time_utildefines.h"
-#endif
-
#include "BLF_api.h"
#include "BLT_translation.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_idcode.h"
#include "BKE_idprop.h"
#include "BKE_fcurve.h"
-#include "BKE_library_override.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "BKE_node.h"
#include "DEG_depsgraph.h"
@@ -67,8 +64,9 @@
#include "WM_types.h"
#include "rna_internal.h"
+#include "rna_access_internal.h"
-const PointerRNA PointerRNA_NULL = {{NULL}};
+const PointerRNA PointerRNA_NULL = {NULL};
/* Init/Exit */
@@ -116,7 +114,7 @@ void RNA_exit(void)
void RNA_main_pointer_create(struct Main *main, PointerRNA *r_ptr)
{
- r_ptr->id.data = NULL;
+ r_ptr->owner_id = NULL;
r_ptr->type = &RNA_BlendData;
r_ptr->data = main;
}
@@ -126,7 +124,7 @@ void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
StructRNA *type, *idtype = NULL;
if (id) {
- PointerRNA tmp = {{NULL}};
+ PointerRNA tmp = {NULL};
tmp.data = id;
idtype = rna_ID_refine(&tmp);
@@ -142,7 +140,7 @@ void RNA_id_pointer_create(ID *id, PointerRNA *r_ptr)
}
}
- r_ptr->id.data = id;
+ r_ptr->owner_id = id;
r_ptr->type = idtype;
r_ptr->data = id;
}
@@ -153,13 +151,13 @@ void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
StructRNA *idtype = NULL;
if (id) {
- PointerRNA tmp = {{0}};
+ PointerRNA tmp = {0};
tmp.data = id;
idtype = rna_ID_refine(&tmp);
}
#endif
- r_ptr->id.data = id;
+ r_ptr->owner_id = id;
r_ptr->type = type;
r_ptr->data = data;
@@ -179,22 +177,22 @@ void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
bool RNA_pointer_is_null(const PointerRNA *ptr)
{
- return !((ptr->data != NULL) && (ptr->id.data != NULL) && (ptr->type != NULL));
+ return !((ptr->data != NULL) && (ptr->owner_id != NULL) && (ptr->type != NULL));
}
static void rna_pointer_inherit_id(StructRNA *type, PointerRNA *parent, PointerRNA *ptr)
{
if (type && type->flag & STRUCT_ID) {
- ptr->id.data = ptr->data;
+ ptr->owner_id = ptr->data;
}
else {
- ptr->id.data = parent->id.data;
+ ptr->owner_id = parent->owner_id;
}
}
void RNA_blender_rna_pointer_create(PointerRNA *r_ptr)
{
- r_ptr->id.data = NULL;
+ r_ptr->owner_id = NULL;
r_ptr->type = &RNA_BlenderRNA;
r_ptr->data = &BLENDER_RNA;
}
@@ -229,7 +227,7 @@ void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr)
#if 0 /* works but this case if covered by more general code below. */
if (RNA_struct_is_ID(ptr->type)) {
/* simple case */
- RNA_id_pointer_create(ptr->id.data, r_ptr);
+ RNA_id_pointer_create(ptr->owner_id, r_ptr);
}
else
#endif
@@ -249,7 +247,7 @@ void RNA_pointer_recast(PointerRNA *ptr, PointerRNA *r_ptr)
/* ID Properties */
-static void rna_idproperty_touch(IDProperty *idprop)
+void rna_idproperty_touch(IDProperty *idprop)
{
/* so the property is seen as 'set' by rna */
idprop->flag &= ~IDP_FLAG_GHOST;
@@ -619,7 +617,7 @@ PropertyRNA *rna_ensure_property_realdata(PropertyRNA **prop, PointerRNA *ptr)
return rna_idproperty_check_ex(prop, ptr, true);
}
-static PropertyRNA *rna_ensure_property(PropertyRNA *prop)
+PropertyRNA *rna_ensure_property(PropertyRNA *prop)
{
/* the quick version if we don't need the idproperty */
@@ -1171,11 +1169,6 @@ int RNA_property_flag(PropertyRNA *prop)
return rna_ensure_property(prop)->flag;
}
-int RNA_property_override_flag(PropertyRNA *prop)
-{
- return rna_ensure_property(prop)->flag_override;
-}
-
/**
* Get the tags set for \a prop as int bitfield.
* \note Doesn't perform any validity check on the set bits. #RNA_def_property_tags does this
@@ -2067,7 +2060,7 @@ int RNA_property_ui_icon(PropertyRNA *prop)
bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
int flag;
const char *dummy_info;
@@ -2085,7 +2078,7 @@ bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop)
*/
bool RNA_property_editable_info(PointerRNA *ptr, PropertyRNA *prop, const char **r_info)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
int flag;
prop = rna_ensure_property(prop);
@@ -2152,7 +2145,7 @@ bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
flag &= prop->itemeditable(ptr, index);
}
- id = ptr->id.data;
+ id = ptr->owner_id;
return (flag & PROP_EDITABLE) && (!id || !ID_IS_LINKED(id) || (prop->flag & PROP_LIB_EXCEPTION));
}
@@ -2160,7 +2153,7 @@ bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index)
bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop)
{
/* check that base ID-block can support animation data */
- if (!id_can_have_animdata(ptr->id.data)) {
+ if (!id_can_have_animdata(ptr->owner_id)) {
return false;
}
@@ -2194,77 +2187,6 @@ bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop)
return false;
}
-
-/** \note Does not take into account editable status, this has to be checked separately
- * (using #RNA_property_editable_flag() usually). */
-bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop)
-{
- if (prop->magic == RNA_MAGIC) {
- /* Special handling for insertions of constraints or modifiers... */
- /* TODO Note We may want to add a more generic system to RNA
- * (like a special property in struct of items)
- * if we get more overrideable collections,
- * for now we can live with those special-cases handling I think. */
- if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
- bConstraint *con = ptr->data;
- if (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) {
- return true;
- }
- }
- else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
- ModifierData *mod = ptr->data;
- if (mod->flag & eModifierFlag_OverrideLibrary_Local) {
- return true;
- }
- }
- /* If this is a RNA-defined property (real or 'virtual' IDProp),
- * we want to use RNA prop flag. */
- return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) &&
- (prop->flag_override & PROPOVERRIDE_OVERRIDABLE_LIBRARY);
- }
- else {
- /* If this is a real 'pure' IDProp (aka custom property), we want to use the IDProp flag. */
- return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) &&
- (((IDProperty *)prop)->flag & IDP_FLAG_OVERRIDABLE_LIBRARY);
- }
-}
-
-/* Should only be used for custom properties */
-bool RNA_property_overridable_library_set(PointerRNA *UNUSED(ptr),
- PropertyRNA *prop,
- const bool is_overridable)
-{
- /* Only works for pure custom properties IDProps. */
- if (prop->magic != RNA_MAGIC) {
- IDProperty *idprop = (IDProperty *)prop;
-
- idprop->flag = is_overridable ? (idprop->flag | IDP_FLAG_OVERRIDABLE_LIBRARY) :
- (idprop->flag & ~IDP_FLAG_OVERRIDABLE_LIBRARY);
- return true;
- }
-
- return false;
-}
-
-bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop)
-{
- char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
- ID *id = ptr->id.data;
-
- if (rna_path == NULL || id == NULL || id->override_library == NULL) {
- return false;
- }
-
- return (BKE_override_library_property_find(id->override_library, rna_path) != NULL);
-}
-
-bool RNA_property_comparable(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
-{
- prop = rna_ensure_property(prop);
-
- return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON);
-}
-
/* this function is to check if its possible to create a valid path from the ID
* its slow so don't call in a loop */
bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
@@ -2277,7 +2199,7 @@ bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop)
PointerRNA r_ptr;
PropertyRNA *r_prop;
- RNA_id_pointer_create(ptr->id.data, &id_ptr);
+ RNA_id_pointer_create(ptr->owner_id, &id_ptr);
if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == true) {
ret = (prop == r_prop);
}
@@ -2316,7 +2238,7 @@ static void rna_property_update(
/* TODO(campbell): Should eventually be replaced entirely by message bus (below)
* for now keep since COW, bugs are hard to track when we have other missing updates. */
if (prop->noteflag) {
- WM_main_add_notifier(prop->noteflag, ptr->id.data);
+ WM_main_add_notifier(prop->noteflag, ptr->owner_id);
}
#endif
@@ -2327,10 +2249,10 @@ static void rna_property_update(
/* we could add NULL check, for now don't */
WM_msg_publish_rna(mbus, ptr, prop);
}
- if (ptr->id.data != NULL && ((prop->flag & PROP_NO_DEG_UPDATE) == 0)) {
- const short id_type = GS(((ID *)ptr->id.data)->name);
+ if (ptr->owner_id != NULL && ((prop->flag & PROP_NO_DEG_UPDATE) == 0)) {
+ const short id_type = GS(ptr->owner_id->name);
if (ID_TYPE_IS_COW(id_type)) {
- DEG_id_tag_update(ptr->id.data, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_COPY_ON_WRITE);
}
}
/* End message bus. */
@@ -2339,14 +2261,14 @@ static void rna_property_update(
if (!is_rna || (prop->flag & PROP_IDPROPERTY)) {
/* WARNING! This is so property drivers update the display!
* not especially nice */
- DEG_id_tag_update(ptr->id.data,
+ DEG_id_tag_update(ptr->owner_id,
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_PARAMETERS);
WM_main_add_notifier(NC_WINDOW, NULL);
/* Not nice as well, but the only way to make sure material preview
* is updated with custom nodes.
*/
- if ((prop->flag & PROP_IDPROPERTY) != 0 && (ptr->id.data != NULL) &&
- (GS(((ID *)ptr->id.data)->name) == ID_NT)) {
+ if ((prop->flag & PROP_IDPROPERTY) != 0 && (ptr->owner_id != NULL) &&
+ (GS(ptr->owner_id->name) == ID_NT)) {
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, NULL);
}
}
@@ -2379,7 +2301,7 @@ void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, Proper
* property updates to actually work).
*
* The cache is structured with a dual-layer structure
- * - L1 = PointerRNA used as key; id.data is used (it should always be defined,
+ * - L1 = PointerRNA used as key; owner_id is used (it should always be defined,
* and most updates end up using just that anyways)
* - L2 = Update functions to be called on those PointerRNA's
*/
@@ -2423,7 +2345,7 @@ void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
* since most update calls that we'll encounter only really care about this. */
/* TODO: later, the cache might need to have some nesting on L1 to cope better
* with these problems + some tagging to indicate we need this */
- if (uce->ptr.id.data == ptr->id.data) {
+ if (uce->ptr.owner_id == ptr->owner_id) {
break;
}
}
@@ -2433,7 +2355,7 @@ void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop)
BLI_addtail(&rna_updates_cache, uce);
/* copy pointer */
- RNA_pointer_create(ptr->id.data, ptr->type, ptr->data, &uce->ptr);
+ RNA_pointer_create(ptr->owner_id, ptr->type, ptr->data, &uce->ptr);
}
/* check on the update func */
@@ -3851,7 +3773,7 @@ void RNA_property_pointer_set(PointerRNA *ptr,
/* RNA */
if (pprop->set && !((prop->flag & PROP_NEVER_NULL) && ptr_value.data == NULL) &&
- !((prop->flag & PROP_ID_SELF_CHECK) && ptr->id.data == ptr_value.id.data)) {
+ !((prop->flag & PROP_ID_SELF_CHECK) && ptr->owner_id == ptr_value.owner_id)) {
pprop->set(ptr, ptr_value, reports);
}
/* IDProperty */
@@ -5440,6 +5362,10 @@ static bool rna_path_parse(PointerRNA *ptr,
* Resolve the given RNA Path to find the pointer and/or property
* indicated by fully resolving the path.
*
+ * \warning Unlike \a RNA_path_resolve_property(), that one *will* try to follow RNAPointers,
+ * e.g. the path 'parent' applied to a RNAObject \a ptr will return the object.parent in \a r_ptr,
+ * and a NULL \a r_prop...
+ *
* \note Assumes all pointers provided are valid
* \return True if path can be resolved to a valid "pointer + property" OR "pointer only"
*/
@@ -5814,14 +5740,14 @@ static char *rna_path_from_ID_to_idpgroup(PointerRNA *ptr)
IDProperty *haystack;
IDProperty *needle;
- BLI_assert(ptr->id.data != NULL);
+ BLI_assert(ptr->owner_id != NULL);
/* TODO, Support Bones/PoseBones. no pointers stored to the bones from here, only the ID.
* See example in T25746.
* Unless this is added only way to find this is to also search
* all bones and pose bones of an armature or object.
*/
- RNA_id_pointer_create(ptr->id.data, &id_ptr);
+ RNA_id_pointer_create(ptr->owner_id, &id_ptr);
haystack = RNA_struct_idprops(&id_ptr, false);
if (haystack) { /* can fail when called on bones */
@@ -5833,11 +5759,79 @@ static char *rna_path_from_ID_to_idpgroup(PointerRNA *ptr)
}
}
+/**
+ * Find the actual ID pointer and path from it to the given ID.
+ *
+ * \param id: ID reference to search the global owner for.
+ * \param[out] r_path: Path from the real ID to the initial ID.
+ * \return The ID pointer, or NULL in case of failure.
+ */
+ID *RNA_find_real_ID_and_path(Main *bmain, ID *id, const char **r_path)
+{
+ if (r_path) {
+ *r_path = "";
+ }
+
+ if ((id != NULL) && (id->flag & LIB_PRIVATE_DATA)) {
+ switch (GS(id->name)) {
+ case ID_NT:
+ if (r_path) {
+ *r_path = "node_tree";
+ }
+ return BKE_node_tree_find_owner_ID(bmain, (bNodeTree *)id);
+ case ID_GR:
+ if (r_path) {
+ *r_path = "collection";
+ }
+ return (ID *)BKE_collection_master_scene_search(bmain, (Collection *)id);
+
+ default:
+ return NULL;
+ }
+ }
+ else {
+ return id;
+ }
+}
+
+static char *rna_prepend_real_ID_path(Main *bmain, ID *id, char *path, ID **r_real_id)
+{
+ if (r_real_id != NULL) {
+ *r_real_id = NULL;
+ }
+
+ const char *prefix;
+ ID *real_id = RNA_find_real_ID_and_path(bmain, id, &prefix);
+
+ if (r_real_id != NULL) {
+ *r_real_id = real_id;
+ }
+
+ if (path != NULL) {
+ char *new_path = NULL;
+
+ if (real_id) {
+ if (prefix[0]) {
+ new_path = BLI_sprintfN("%s%s%s", prefix, path[0] == '[' ? "" : ".", path);
+ }
+ else {
+ return path;
+ }
+ }
+
+ MEM_freeN(path);
+ return new_path;
+ }
+ else {
+ return prefix[0] != '\0' ? BLI_strdup(prefix) : NULL;
+ }
+}
+
char *RNA_path_from_ID_to_struct(PointerRNA *ptr)
{
char *ptrpath = NULL;
- if (!ptr->id.data || !ptr->data) {
+ if (!ptr->owner_id || !ptr->data) {
return NULL;
}
@@ -5853,7 +5847,7 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr)
/* find the property in the struct we're nested in that references this struct, and
* use its identifier as the first part of the path used...
*/
- RNA_id_pointer_create(ptr->id.data, &parentptr);
+ RNA_id_pointer_create(ptr->owner_id, &parentptr);
userprop = RNA_struct_find_nested(&parentptr, ptr->type);
if (userprop) {
@@ -5875,6 +5869,13 @@ char *RNA_path_from_ID_to_struct(PointerRNA *ptr)
return ptrpath;
}
+char *RNA_path_from_real_ID_to_struct(Main *bmain, PointerRNA *ptr, struct ID **r_real)
+{
+ char *path = RNA_path_from_ID_to_struct(ptr);
+
+ return rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real);
+}
+
static void rna_path_array_multi_from_flat_index(const int dimsize[RNA_MAX_ARRAY_LENGTH],
const int totdims,
const int index_dim,
@@ -5929,7 +5930,7 @@ char *RNA_path_from_ID_to_property_index(PointerRNA *ptr,
const char *propname;
char *ptrpath, *path;
- if (!ptr->id.data || !ptr->data) {
+ if (!ptr->owner_id || !ptr->data) {
return NULL;
}
@@ -5981,6 +5982,14 @@ char *RNA_path_from_ID_to_property(PointerRNA *ptr, PropertyRNA *prop)
return RNA_path_from_ID_to_property_index(ptr, prop, 0, -1);
}
+char *RNA_path_from_real_ID_to_property_index(
+ Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index_dim, int index, ID **r_real_id)
+{
+ char *path = RNA_path_from_ID_to_property_index(ptr, prop, index_dim, index);
+
+ return rna_prepend_real_ID_path(bmain, ptr->owner_id, path, r_real_id);
+}
+
/**
* \return the path to given ptr/prop from the closest ancestor of given type,
* if any (else return NULL).
@@ -6000,7 +6009,7 @@ char *RNA_path_resolve_from_type_to_property(PointerRNA *ptr,
return NULL;
}
- RNA_id_pointer_create(ptr->id.data, &idptr);
+ RNA_id_pointer_create(ptr->owner_id, &idptr);
if (RNA_path_resolve_elements(&idptr, full_path, &path_elems)) {
PropertyElemRNA *prop_elem;
@@ -6027,32 +6036,46 @@ char *RNA_path_resolve_from_type_to_property(PointerRNA *ptr,
* Get the ID as a python representation, eg:
* bpy.data.foo["bar"]
*/
-char *RNA_path_full_ID_py(ID *id)
+char *RNA_path_full_ID_py(Main *bmain, ID *id)
{
+ const char *path;
+ ID *id_real = RNA_find_real_ID_and_path(bmain, id, &path);
+
+ if (id_real) {
+ id = id_real;
+ }
+ else {
+ path = "";
+ }
+
char id_esc[(sizeof(id->name) - 2) * 2];
BLI_strescape(id_esc, id->name + 2, sizeof(id_esc));
- return BLI_sprintfN("bpy.data.%s[\"%s\"]", BKE_idcode_to_name_plural(GS(id->name)), id_esc);
+ return BLI_sprintfN("bpy.data.%s[\"%s\"]%s%s",
+ BKE_idcode_to_name_plural(GS(id->name)),
+ id_esc,
+ path[0] ? "." : "",
+ path);
}
/**
* Get the ID.struct as a python representation, eg:
* bpy.data.foo["bar"].some_struct
*/
-char *RNA_path_full_struct_py(struct PointerRNA *ptr)
+char *RNA_path_full_struct_py(Main *bmain, struct PointerRNA *ptr)
{
char *id_path;
char *data_path;
char *ret;
- if (!ptr->id.data) {
+ if (!ptr->owner_id) {
return NULL;
}
/* never fails */
- id_path = RNA_path_full_ID_py(ptr->id.data);
+ id_path = RNA_path_full_ID_py(bmain, ptr->owner_id);
data_path = RNA_path_from_ID_to_struct(ptr);
@@ -6072,10 +6095,8 @@ char *RNA_path_full_struct_py(struct PointerRNA *ptr)
* Get the ID.struct.property as a python representation, eg:
* bpy.data.foo["bar"].some_struct.some_prop[10]
*/
-char *RNA_path_full_property_py_ex(PointerRNA *ptr,
- PropertyRNA *prop,
- int index,
- bool use_fallback)
+char *RNA_path_full_property_py_ex(
+ Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index, bool use_fallback)
{
char *id_path;
const char *data_delim;
@@ -6084,12 +6105,12 @@ char *RNA_path_full_property_py_ex(PointerRNA *ptr,
char *ret;
- if (!ptr->id.data) {
+ if (!ptr->owner_id) {
return NULL;
}
/* never fails */
- id_path = RNA_path_full_ID_py(ptr->id.data);
+ id_path = RNA_path_full_ID_py(bmain, ptr->owner_id);
data_path = RNA_path_from_ID_to_property(ptr, prop);
if (data_path) {
@@ -6122,9 +6143,9 @@ char *RNA_path_full_property_py_ex(PointerRNA *ptr,
return ret;
}
-char *RNA_path_full_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
+char *RNA_path_full_property_py(Main *bmain, PointerRNA *ptr, PropertyRNA *prop, int index)
{
- return RNA_path_full_property_py_ex(ptr, prop, index, false);
+ return RNA_path_full_property_py_ex(bmain, ptr, prop, index, false);
}
/**
@@ -6137,7 +6158,7 @@ char *RNA_path_struct_property_py(PointerRNA *ptr, PropertyRNA *prop, int index)
char *ret;
- if (!ptr->id.data) {
+ if (!ptr->owner_id) {
return NULL;
}
@@ -6722,16 +6743,16 @@ char *RNA_pointer_as_string_id(bContext *C, PointerRNA *ptr)
return cstring;
}
-static char *rna_pointer_as_string__bldata(PointerRNA *ptr)
+static char *rna_pointer_as_string__bldata(Main *bmain, PointerRNA *ptr)
{
- if (ptr->type == NULL || ptr->id.data == NULL) {
+ if (ptr->type == NULL || ptr->owner_id == NULL) {
return BLI_strdup("None");
}
else if (RNA_struct_is_ID(ptr->type)) {
- return RNA_path_full_ID_py(ptr->id.data);
+ return RNA_path_full_ID_py(bmain, ptr->owner_id);
}
else {
- return RNA_path_full_struct_py(ptr);
+ return RNA_path_full_struct_py(bmain, ptr);
}
}
@@ -6748,7 +6769,7 @@ char *RNA_pointer_as_string(bContext *C,
return RNA_pointer_as_string_id(C, ptr_prop);
}
else {
- return rna_pointer_as_string__bldata(ptr_prop);
+ return rna_pointer_as_string__bldata(CTX_data_main(C), ptr_prop);
}
}
@@ -8115,59 +8136,6 @@ bool RNA_property_assign_default(PointerRNA *ptr, PropertyRNA *prop)
}
}
-static bool rna_property_override_operation_apply(Main *bmain,
- PointerRNA *ptr_local,
- PointerRNA *ptr_override,
- PointerRNA *ptr_storage,
- PropertyRNA *prop_local,
- PropertyRNA *prop_override,
- PropertyRNA *prop_storage,
- PointerRNA *ptr_item_local,
- PointerRNA *ptr_item_override,
- PointerRNA *ptr_item_storage,
- IDOverrideLibraryPropertyOperation *opop);
-
-bool RNA_property_copy(
- Main *bmain, PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index)
-{
- if (!RNA_property_editable(ptr, prop)) {
- return false;
- }
-
- PropertyRNA *prop_dst = prop;
- PropertyRNA *prop_src = prop;
-
- /* Ensure we get real property data,
- * be it an actual RNA property, or an IDProperty in disguise. */
- prop_dst = rna_ensure_property_realdata(&prop_dst, ptr);
- prop_src = rna_ensure_property_realdata(&prop_src, fromptr);
-
- /* IDprops: destination may not exist, if source does and is set, try to create it. */
- /* Note: this is sort of quick hack/bandage to fix the issue,
- * we need to rethink how IDProps are handled in 'diff' RNA code completely, imho... */
- if (prop_src != NULL && prop_dst == NULL && RNA_property_is_set(fromptr, prop)) {
- BLI_assert(prop_src->magic != RNA_MAGIC);
- IDProperty *idp_dst = RNA_struct_idprops(ptr, true);
- IDProperty *prop_idp_dst = IDP_CopyProperty((IDProperty *)prop_src);
- IDP_AddToGroup(idp_dst, prop_idp_dst);
- rna_idproperty_touch(prop_idp_dst);
- /* Nothing else to do here... */
- return true;
- }
-
- if (ELEM(NULL, prop_dst, prop_src)) {
- return false;
- }
-
- IDOverrideLibraryPropertyOperation opop = {
- .operation = IDOVERRIDE_LIBRARY_OP_REPLACE,
- .subitem_reference_index = index,
- .subitem_local_index = index,
- };
- return rna_property_override_operation_apply(
- bmain, ptr, fromptr, NULL, prop_dst, prop_src, NULL, NULL, NULL, NULL, &opop);
-}
-
/* use RNA_warning macro which includes __func__ suffix */
void _RNA_warning(const char *format, ...)
{
@@ -8190,865 +8158,6 @@ void _RNA_warning(const char *format, ...)
#endif
}
-static int rna_property_override_diff(Main *bmain,
- PointerRNA *ptr_a,
- PointerRNA *ptr_b,
- PropertyRNA *prop,
- PropertyRNA *prop_a,
- PropertyRNA *prop_b,
- const char *rna_path,
- eRNACompareMode mode,
- IDOverrideLibrary *override,
- const int flags,
- eRNAOverrideMatchResult *r_report_flags);
-
-bool RNA_property_equals(
- Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, eRNACompareMode mode)
-{
- BLI_assert(ELEM(mode, RNA_EQ_STRICT, RNA_EQ_UNSET_MATCH_ANY, RNA_EQ_UNSET_MATCH_NONE));
-
- return (rna_property_override_diff(
- bmain, ptr_a, ptr_b, prop, NULL, NULL, NULL, mode, NULL, 0, NULL) == 0);
-}
-
-bool RNA_struct_equals(Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, eRNACompareMode mode)
-{
- CollectionPropertyIterator iter;
- PropertyRNA *iterprop;
- bool equals = true;
-
- if (ptr_a == NULL && ptr_b == NULL) {
- return true;
- }
- else if (ptr_a == NULL || ptr_b == NULL) {
- return false;
- }
- else if (ptr_a->type != ptr_b->type) {
- return false;
- }
-
- iterprop = RNA_struct_iterator_property(ptr_a->type);
-
- RNA_property_collection_begin(ptr_a, iterprop, &iter);
- for (; iter.valid; RNA_property_collection_next(&iter)) {
- PropertyRNA *prop = iter.ptr.data;
-
- if (!RNA_property_equals(bmain, ptr_a, ptr_b, prop, mode)) {
- equals = false;
- break;
- }
- }
- RNA_property_collection_end(&iter);
-
- return equals;
-}
-
-/* Low-level functions, also used by non-override RNA API like copy or equality check. */
-
-/** Generic RNA property diff function.
- *
- * \note about \a prop and \a prop_a/prop_b parameters:
- * the former is expected to be an 'un-resolved' one,
- * while the two later are expected to be fully resolved ones
- * (i.e. to be the IDProps when they should be, etc.).
- * When \a prop is given, \a prop_a and \a prop_b should always be NULL, and vice-versa.
- * This is necessary, because we cannot perform 'set/unset' checks on resolved properties
- * (unset IDProps would merely be NULL then).
- *
- * \note When there is no equality,
- * but we cannot determine an order (greater than/lesser than), we return 1.
- */
-static int rna_property_override_diff(Main *bmain,
- PointerRNA *ptr_a,
- PointerRNA *ptr_b,
- PropertyRNA *prop,
- PropertyRNA *prop_a,
- PropertyRNA *prop_b,
- const char *rna_path,
- eRNACompareMode mode,
- IDOverrideLibrary *override,
- const int flags,
- eRNAOverrideMatchResult *r_report_flags)
-{
- if (prop != NULL) {
- BLI_assert(prop_a == NULL && prop_b == NULL);
- prop_a = prop;
- prop_b = prop;
- }
-
- if (ELEM(NULL, prop_a, prop_b)) {
- return (prop_a == prop_b) ? 0 : 1;
- }
-
- if (!RNA_property_comparable(ptr_a, prop_a) || !RNA_property_comparable(ptr_b, prop_b)) {
- return 0;
- }
-
- if (mode == RNA_EQ_UNSET_MATCH_ANY) {
- /* uninitialized properties are assumed to match anything */
- if (!RNA_property_is_set(ptr_a, prop_a) || !RNA_property_is_set(ptr_b, prop_b)) {
- return 0;
- }
- }
- else if (mode == RNA_EQ_UNSET_MATCH_NONE) {
- /* unset properties never match set properties */
- if (RNA_property_is_set(ptr_a, prop_a) != RNA_property_is_set(ptr_b, prop_b)) {
- return 1;
- }
- }
-
- if (prop != NULL) {
- /* Ensure we get real property data, be it an actual RNA property,
- * or an IDProperty in disguise. */
- prop_a = rna_ensure_property_realdata(&prop_a, ptr_a);
- prop_b = rna_ensure_property_realdata(&prop_b, ptr_b);
-
- if (ELEM(NULL, prop_a, prop_b)) {
- return (prop_a == prop_b) ? 0 : 1;
- }
- }
-
- /* Check if we are working with arrays. */
- const bool is_array_a = RNA_property_array_check(prop_a);
- const bool is_array_b = RNA_property_array_check(prop_b);
-
- if (is_array_a != is_array_b) {
- /* Should probably never happen actually... */
- BLI_assert(0);
- return is_array_a ? 1 : -1;
- }
-
- /* Get the length of the array to work with. */
- const int len_a = RNA_property_array_length(ptr_a, prop_a);
- const int len_b = RNA_property_array_length(ptr_b, prop_b);
-
- if (len_a != len_b) {
- /* Do not handle override in that case,
- * we do not support insertion/deletion from arrays for now. */
- return len_a > len_b ? 1 : -1;
- }
-
- if (is_array_a && len_a == 0) {
- /* Empty arrays, will happen in some case with dynamic ones. */
- return 0;
- }
-
- RNAPropOverrideDiff override_diff = NULL;
- /* Special case for IDProps, we use default callback then. */
- if (prop_a->magic != RNA_MAGIC) {
- override_diff = rna_property_override_diff_default;
- if (prop_b->magic == RNA_MAGIC && prop_b->override_diff != override_diff) {
- override_diff = NULL;
- }
- }
- else if (prop_b->magic != RNA_MAGIC) {
- override_diff = rna_property_override_diff_default;
- if (prop_a->override_diff != override_diff) {
- override_diff = NULL;
- }
- }
- else if (prop_a->override_diff == prop_b->override_diff) {
- override_diff = prop_a->override_diff;
- }
-
- if (override_diff == NULL) {
-#ifndef NDEBUG
- printf("'%s' gives unmatching or NULL RNA diff callbacks, should not happen (%d vs. %d).\n",
- rna_path ?
- rna_path :
- (prop_a->magic != RNA_MAGIC ? ((IDProperty *)prop_a)->name : prop_a->identifier),
- prop_a->magic == RNA_MAGIC,
- prop_b->magic == RNA_MAGIC);
-#endif
- BLI_assert(0);
- return 1;
- }
-
- bool override_changed = false;
- int diff_flags = flags;
- if (!RNA_property_overridable_get(ptr_a, prop_a)) {
- diff_flags &= ~RNA_OVERRIDE_COMPARE_CREATE;
- }
- const int diff = override_diff(bmain,
- ptr_a,
- ptr_b,
- prop_a,
- prop_b,
- len_a,
- len_b,
- mode,
- override,
- rna_path,
- diff_flags,
- &override_changed);
- if (override_changed && r_report_flags) {
- *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_CREATED;
- }
-
- return diff;
-}
-
-/* Modify local data-block to make it ready for override application
- * (only needed for diff operations, where we use
- * the local data-block's data as second operand). */
-static bool rna_property_override_operation_store(Main *bmain,
- PointerRNA *ptr_local,
- PointerRNA *ptr_reference,
- PointerRNA *ptr_storage,
- PropertyRNA *prop_local,
- PropertyRNA *prop_reference,
- PropertyRNA *prop_storage,
- IDOverrideLibraryProperty *op)
-{
- int len_local, len_reference, len_storage = 0;
- bool changed = false;
-
- if (ptr_storage == NULL) {
- return changed;
- }
-
- /* get the length of the array to work with */
- len_local = RNA_property_array_length(ptr_local, prop_local);
- len_reference = RNA_property_array_length(ptr_reference, prop_reference);
- if (prop_storage) {
- len_storage = RNA_property_array_length(ptr_storage, prop_storage);
- }
-
- if (len_local != len_reference || len_local != len_storage) {
- /* Do not handle override in that case,
- * we do not support insertion/deletion from arrays for now. */
- return changed;
- }
-
- BLI_assert(prop_local->override_store == prop_reference->override_store &&
- (!ptr_storage || prop_local->override_store == prop_storage->override_store) &&
- prop_local->override_store != NULL);
-
- for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
- /* Only needed for diff operations. */
- if (!ELEM(opop->operation,
- IDOVERRIDE_LIBRARY_OP_ADD,
- IDOVERRIDE_LIBRARY_OP_SUBTRACT,
- IDOVERRIDE_LIBRARY_OP_MULTIPLY)) {
- continue;
- }
-
- if (prop_local->override_store(bmain,
- ptr_local,
- ptr_reference,
- ptr_storage,
- prop_local,
- prop_reference,
- prop_storage,
- len_local,
- len_reference,
- len_storage,
- opop)) {
- changed = true;
- }
- }
-
- return changed;
-}
-
-static bool rna_property_override_operation_apply(Main *bmain,
- PointerRNA *ptr_local,
- PointerRNA *ptr_override,
- PointerRNA *ptr_storage,
- PropertyRNA *prop_local,
- PropertyRNA *prop_override,
- PropertyRNA *prop_storage,
- PointerRNA *ptr_item_local,
- PointerRNA *ptr_item_override,
- PointerRNA *ptr_item_storage,
- IDOverrideLibraryPropertyOperation *opop)
-{
- int len_local, len_reference, len_storage = 0;
-
- const short override_op = opop->operation;
-
- if (override_op == IDOVERRIDE_LIBRARY_OP_NOOP) {
- return true;
- }
-
- if (ELEM(override_op,
- IDOVERRIDE_LIBRARY_OP_ADD,
- IDOVERRIDE_LIBRARY_OP_SUBTRACT,
- IDOVERRIDE_LIBRARY_OP_MULTIPLY) &&
- !ptr_storage) {
- /* We cannot apply 'diff' override operations without some reference storage.
- * This should typically only happen at read time of .blend file... */
- return false;
- }
-
- if (ELEM(override_op,
- IDOVERRIDE_LIBRARY_OP_ADD,
- IDOVERRIDE_LIBRARY_OP_SUBTRACT,
- IDOVERRIDE_LIBRARY_OP_MULTIPLY) &&
- !prop_storage) {
- /* We cannot apply 'diff' override operations without some reference storage.
- * This should typically only happen at read time of .blend file... */
- return false;
- }
-
- RNAPropOverrideApply override_apply = NULL;
- /* Special case for IDProps, we use default callback then. */
- if (prop_local->magic != RNA_MAGIC) {
- override_apply = rna_property_override_apply_default;
- if (prop_override->magic == RNA_MAGIC && prop_override->override_apply != override_apply) {
- override_apply = NULL;
- }
- }
- else if (prop_override->magic != RNA_MAGIC) {
- override_apply = rna_property_override_apply_default;
- if (prop_local->override_apply != override_apply) {
- override_apply = NULL;
- }
- }
- else if (prop_local->override_apply == prop_override->override_apply) {
- override_apply = prop_local->override_apply;
- }
-
- if (ptr_storage && prop_storage->magic == RNA_MAGIC &&
- prop_storage->override_apply != override_apply) {
- override_apply = NULL;
- }
-
- if (override_apply == NULL) {
-#ifndef NDEBUG
- printf("'%s' gives unmatching or NULL RNA copy callbacks, should not happen (%d vs. %d).\n",
- prop_local->magic != RNA_MAGIC ? ((IDProperty *)prop_local)->name :
- prop_local->identifier,
- prop_local->magic == RNA_MAGIC,
- prop_override->magic == RNA_MAGIC);
-#endif
- BLI_assert(0);
- return false;
- }
-
- /* get the length of the array to work with */
- len_local = RNA_property_array_length(ptr_local, prop_local);
- len_reference = RNA_property_array_length(ptr_override, prop_override);
- if (ptr_storage) {
- len_storage = RNA_property_array_length(ptr_storage, prop_storage);
- }
-
- if (len_local != len_reference || (ptr_storage && len_local != len_storage)) {
- /* Do not handle override in that case,
- * we do not support insertion/deletion from arrays for now. */
- return false;
- }
-
- /* get and set the default values as appropriate for the various types */
- return override_apply(bmain,
- ptr_local,
- ptr_override,
- ptr_storage,
- prop_local,
- prop_override,
- prop_storage,
- len_local,
- len_reference,
- len_storage,
- ptr_item_local,
- ptr_item_override,
- ptr_item_storage,
- opop);
-}
-
-/**
- * Check whether reference and local overridden data match (are the same),
- * with respect to given restrictive sets of properties.
- * If requested, will generate needed new property overrides, and/or restore values from reference.
- *
- * \param r_report_flags: If given,
- * will be set with flags matching actions taken by the function on \a ptr_local.
- *
- * \return True if _resulting_ \a ptr_local does match \a ptr_reference.
- */
-bool RNA_struct_override_matches(Main *bmain,
- PointerRNA *ptr_local,
- PointerRNA *ptr_reference,
- const char *root_path,
- IDOverrideLibrary *override,
- const eRNAOverrideMatch flags,
- eRNAOverrideMatchResult *r_report_flags)
-{
- CollectionPropertyIterator iter;
- PropertyRNA *iterprop;
- bool matching = true;
-
- BLI_assert(ptr_local->type == ptr_reference->type);
- BLI_assert(ptr_local->id.data && ptr_reference->id.data);
-
- const bool ignore_non_overridable = (flags & RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE) != 0;
- const bool ignore_overridden = (flags & RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN) != 0;
- const bool do_create = (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0;
- const bool do_restore = (flags & RNA_OVERRIDE_COMPARE_RESTORE) != 0;
-
-//#define DEBUG_OVERRIDE_TIMEIT
-#ifdef DEBUG_OVERRIDE_TIMEIT
- static float _sum_time_global = 0.0f;
- static float _num_time_global = 0.0f;
- double _timeit_time_global;
- static float _sum_time_diffing = 0.0f;
- static float _delta_time_diffing = 0.0f;
- static int _num_delta_time_diffing = 0.0f;
- static float _num_time_diffing = 0.0f;
- double _timeit_time_diffing;
-
- if (!root_path) {
- _delta_time_diffing = 0.0f;
- _num_delta_time_diffing = 0;
- _timeit_time_global = PIL_check_seconds_timer();
- }
-#endif
-
- iterprop = RNA_struct_iterator_property(ptr_local->type);
-
- for (RNA_property_collection_begin(ptr_local, iterprop, &iter); iter.valid;
- RNA_property_collection_next(&iter)) {
- PropertyRNA *prop_local = iter.ptr.data;
- PropertyRNA *prop_reference = iter.ptr.data;
-
- /* Ensure we get real property data, be it an actual RNA property,
- * or an IDProperty in disguise. */
- prop_local = rna_ensure_property_realdata(&prop_local, ptr_local);
- prop_reference = rna_ensure_property_realdata(&prop_reference, ptr_reference);
-
- if (ELEM(NULL, prop_local, prop_reference)) {
- continue;
- }
-
- if (ignore_non_overridable && !RNA_property_overridable_get(ptr_local, prop_local)) {
- continue;
- }
-
-#if 0 /* This actually makes things slower, since it has to check for animation paths etc! */
- if (RNA_property_animated(ptr_local, prop_local)) {
- /* We cannot do anything here really, animation is some kind of dynamic overrides that has
- * precedence over static one... */
- continue;
- }
-#endif
-
-#define RNA_PATH_BUFFSIZE 8192
-#define RNA_PATH_PRINTF(_str, ...) \
- if (BLI_snprintf(rna_path, RNA_PATH_BUFFSIZE, (_str), __VA_ARGS__) >= RNA_PATH_BUFFSIZE) { \
- rna_path = BLI_sprintfN((_str), __VA_ARGS__); \
- } \
- (void)0
-#define RNA_PATH_FREE \
- if (rna_path != rna_path_buffer) \
- MEM_freeN(rna_path)
-
- char rna_path_buffer[RNA_PATH_BUFFSIZE];
- char *rna_path = rna_path_buffer;
-
- /* XXX TODO this will have to be refined to handle collections insertions, and array items */
- if (root_path) {
- /* Inlined building, much much more efficient. */
- if (prop_local->magic == RNA_MAGIC) {
- RNA_PATH_PRINTF("%s.%s", root_path, RNA_property_identifier(prop_local));
- }
- else {
- RNA_PATH_PRINTF("%s[\"%s\"]", root_path, RNA_property_identifier(prop_local));
- }
- }
- else {
- /* This is rather slow, but is not much called, so not really worth optimizing. */
- rna_path = RNA_path_from_ID_to_property(ptr_local, prop_local);
- }
- if (rna_path == NULL) {
- continue;
- }
-
- // printf("Override Checking %s\n", rna_path);
-
- if (ignore_overridden && BKE_override_library_property_find(override, rna_path) != NULL) {
- RNA_PATH_FREE;
- continue;
- }
-
-#ifdef DEBUG_OVERRIDE_TIMEIT
- if (!root_path) {
- _timeit_time_diffing = PIL_check_seconds_timer();
- }
-#endif
-
- eRNAOverrideMatchResult report_flags = 0;
- const int diff = rna_property_override_diff(bmain,
- ptr_local,
- ptr_reference,
- NULL,
- prop_local,
- prop_reference,
- rna_path,
- RNA_EQ_STRICT,
- override,
- flags,
- &report_flags);
-
-#ifdef DEBUG_OVERRIDE_TIMEIT
- if (!root_path) {
- const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_diffing);
- _delta_time_diffing += _delta_time;
- _num_delta_time_diffing++;
- }
-#endif
-
- matching = matching && diff == 0;
- if (r_report_flags) {
- *r_report_flags |= report_flags;
- }
-
- if (diff != 0) {
- /* XXX TODO: refine this for per-item overriding of arrays... */
- IDOverrideLibraryProperty *op = BKE_override_library_property_find(override, rna_path);
- IDOverrideLibraryPropertyOperation *opop = op ? op->operations.first : NULL;
-
- if (do_restore && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0) {
- /* We are allowed to restore to reference's values. */
- if (ELEM(NULL, op, opop) || opop->operation == IDOVERRIDE_LIBRARY_OP_NOOP) {
- /* We should restore that property to its reference value */
- if (RNA_property_editable(ptr_local, prop_local)) {
- IDOverrideLibraryPropertyOperation opop_tmp = {
- .operation = IDOVERRIDE_LIBRARY_OP_REPLACE,
- .subitem_reference_index = -1,
- .subitem_local_index = -1,
- };
- rna_property_override_operation_apply(bmain,
- ptr_local,
- ptr_reference,
- NULL,
- prop_local,
- prop_reference,
- NULL,
- NULL,
- NULL,
- NULL,
- &opop_tmp);
- if (r_report_flags) {
- *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_RESTORED;
- }
- }
- else {
- /* Too noisy for now, this triggers on runtime props like transform matrices etc. */
-#if 0
- BLI_assert(!"We have differences between reference and "
- "overriding data on non-editable property.");
-#endif
- matching = false;
- }
- }
- }
- else if ((report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0 && ELEM(NULL, op, opop)) {
- /* This property is not overridden, and differs from reference, so we have no match. */
- matching = false;
- if (!(do_create || do_restore)) {
- /* Since we have no 'changing' action allowed, we can break here. */
- MEM_SAFE_FREE(rna_path);
- break;
- }
- }
- }
-
- RNA_PATH_FREE;
-
-#undef RNA_PATH_BUFFSIZE
-#undef RNA_PATH_PRINTF
-#undef RNA_PATH_FREE
- }
- RNA_property_collection_end(&iter);
-
-#ifdef DEBUG_OVERRIDE_TIMEIT
- if (!root_path) {
- const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_global);
- _sum_time_global += _delta_time;
- _num_time_global++;
- _sum_time_diffing += _delta_time_diffing;
- _num_time_diffing++;
- printf("ID: %s\n", ((ID *)ptr_local->id.data)->name);
- printf("time end (%s): %.6f\n", __func__, _delta_time);
- printf("time averaged (%s): %.6f (total: %.6f, in %d runs)\n",
- __func__,
- (_sum_time_global / _num_time_global),
- _sum_time_global,
- (int)_num_time_global);
- printf("diffing time end (%s): %.6f (in %d runs)\n",
- __func__,
- _delta_time_diffing,
- _num_delta_time_diffing);
- printf("diffing time averaged (%s): %.6f (total: %.6f, in %d runs)\n",
- __func__,
- (_sum_time_diffing / _num_time_diffing),
- _sum_time_diffing,
- (int)_num_time_diffing);
- }
-#endif
-
- return matching;
-}
-
-/** Store needed second operands into \a storage data-block
- * for differential override operations. */
-bool RNA_struct_override_store(Main *bmain,
- PointerRNA *ptr_local,
- PointerRNA *ptr_reference,
- PointerRNA *ptr_storage,
- IDOverrideLibrary *override)
-{
- bool changed = false;
-
-#ifdef DEBUG_OVERRIDE_TIMEIT
- TIMEIT_START_AVERAGED(RNA_struct_override_store);
-#endif
- for (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) {
- /* Simplified for now! */
- PointerRNA data_reference, data_local;
- PropertyRNA *prop_reference, *prop_local;
-
- if (RNA_path_resolve_property(ptr_local, op->rna_path, &data_local, &prop_local) &&
- RNA_path_resolve_property(ptr_reference, op->rna_path, &data_reference, &prop_reference)) {
- PointerRNA data_storage;
- PropertyRNA *prop_storage = NULL;
-
- /* It is totally OK if this does not success,
- * only a subset of override operations actually need storage. */
- if (ptr_storage && (ptr_storage->id.data != NULL)) {
- RNA_path_resolve_property(ptr_storage, op->rna_path, &data_storage, &prop_storage);
- }
-
- if (rna_property_override_operation_store(bmain,
- &data_local,
- &data_reference,
- &data_storage,
- prop_reference,
- prop_local,
- prop_storage,
- op)) {
- changed = true;
- }
- }
- }
-#ifdef DEBUG_OVERRIDE_TIMEIT
- TIMEIT_END_AVERAGED(RNA_struct_override_store);
-#endif
-
- return changed;
-}
-
-static void rna_property_override_apply_ex(Main *bmain,
- PointerRNA *ptr_local,
- PointerRNA *ptr_override,
- PointerRNA *ptr_storage,
- PropertyRNA *prop_local,
- PropertyRNA *prop_override,
- PropertyRNA *prop_storage,
- PointerRNA *ptr_item_local,
- PointerRNA *ptr_item_override,
- PointerRNA *ptr_item_storage,
- IDOverrideLibraryProperty *op,
- const bool do_insert)
-{
- for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
- if (!do_insert != !ELEM(opop->operation,
- IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
- IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE)) {
- if (!do_insert) {
- printf("Skipping insert override operations in first pass (%s)!\n", op->rna_path);
- }
- continue;
- }
- if (!rna_property_override_operation_apply(bmain,
- ptr_local,
- ptr_override,
- ptr_storage,
- prop_local,
- prop_override,
- prop_storage,
- ptr_item_local,
- ptr_item_override,
- ptr_item_storage,
- opop)) {
- /* TODO No assert here, would be much much better to just report as warning,
- * failing override applications will probably be fairly common! */
- BLI_assert(0);
- }
- }
-}
-
-/** Apply given \a override operations on \a ptr_local, using \a ptr_override
- * (and \a ptr_storage form differential ops) as source. */
-void RNA_struct_override_apply(Main *bmain,
- PointerRNA *ptr_local,
- PointerRNA *ptr_override,
- PointerRNA *ptr_storage,
- IDOverrideLibrary *override)
-{
-#ifdef DEBUG_OVERRIDE_TIMEIT
- TIMEIT_START_AVERAGED(RNA_struct_override_apply);
-#endif
- /* Note: Applying insert operations in a separate pass is mandatory.
- * We could optimize this later, but for now, as inefficient as it is,
- * don't think this is a critical point.
- */
- bool do_insert = false;
- for (int i = 0; i < 2; i++, do_insert = true) {
- for (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) {
- /* Simplified for now! */
- PointerRNA data_override, data_local;
- PointerRNA data_item_override, data_item_local;
- PropertyRNA *prop_override, *prop_local;
-
- if (RNA_path_resolve_property_and_item_pointer(
- ptr_local, op->rna_path, &data_local, &prop_local, &data_item_local) &&
- RNA_path_resolve_property_and_item_pointer(
- ptr_override, op->rna_path, &data_override, &prop_override, &data_item_override)) {
- PointerRNA data_storage, data_item_storage;
- PropertyRNA *prop_storage = NULL;
-
- /* It is totally OK if this does not success,
- * only a subset of override operations actually need storage. */
- if (ptr_storage && (ptr_storage->id.data != NULL)) {
- RNA_path_resolve_property_and_item_pointer(
- ptr_storage, op->rna_path, &data_storage, &prop_storage, &data_item_storage);
- }
-
- rna_property_override_apply_ex(bmain,
- &data_local,
- &data_override,
- prop_storage ? &data_storage : NULL,
- prop_local,
- prop_override,
- prop_storage,
- &data_item_local,
- &data_item_override,
- prop_storage ? &data_item_storage : NULL,
- op,
- do_insert);
- }
-#ifndef NDEBUG
- else {
- printf(
- "Failed to apply library override operation to '%s.%s' "
- "(could not resolve some properties, local: %d, override: %d)\n",
- ((ID *)ptr_override->id.data)->name,
- op->rna_path,
- RNA_path_resolve_property(ptr_local, op->rna_path, &data_local, &prop_local),
- RNA_path_resolve_property(ptr_override, op->rna_path, &data_override, &prop_override));
- }
-#endif
- }
- }
-#ifdef DEBUG_OVERRIDE_TIMEIT
- TIMEIT_END_AVERAGED(RNA_struct_override_apply);
-#endif
-}
-
-IDOverrideLibraryProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop)
-{
- ID *id = ptr->id.data;
-
- if (!id || !id->override_library) {
- return NULL;
- }
-
- char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
- if (rna_path) {
- IDOverrideLibraryProperty *op = BKE_override_library_property_find(id->override_library,
- rna_path);
- MEM_freeN(rna_path);
- return op;
- }
- return NULL;
-}
-
-IDOverrideLibraryProperty *RNA_property_override_property_get(PointerRNA *ptr,
- PropertyRNA *prop,
- bool *r_created)
-{
- ID *id = ptr->id.data;
-
- if (!id || !id->override_library) {
- return NULL;
- }
-
- char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
- if (rna_path) {
- IDOverrideLibraryProperty *op = BKE_override_library_property_get(
- id->override_library, rna_path, r_created);
- MEM_freeN(rna_path);
- return op;
- }
- return NULL;
-}
-
-IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_find(
- PointerRNA *ptr, PropertyRNA *prop, const int index, const bool strict, bool *r_strict)
-{
- IDOverrideLibraryProperty *op = RNA_property_override_property_find(ptr, prop);
-
- if (!op) {
- return NULL;
- }
-
- return BKE_override_library_property_operation_find(
- op, NULL, NULL, index, index, strict, r_strict);
-}
-
-IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_get(
- PointerRNA *ptr,
- PropertyRNA *prop,
- const short operation,
- const int index,
- const bool strict,
- bool *r_strict,
- bool *r_created)
-{
- IDOverrideLibraryProperty *op = RNA_property_override_property_get(ptr, prop, NULL);
-
- if (!op) {
- return NULL;
- }
-
- return BKE_override_library_property_operation_get(
- op, operation, NULL, NULL, index, index, strict, r_strict, r_created);
-}
-
-eRNAOverrideStatus RNA_property_override_library_status(PointerRNA *ptr,
- PropertyRNA *prop,
- const int index)
-{
- int override_status = 0;
-
- if (!BKE_override_library_is_enabled()) {
- return override_status;
- }
-
- if (!ptr || !prop || !ptr->id.data || !((ID *)ptr->id.data)->override_library) {
- return override_status;
- }
-
- if (RNA_property_overridable_get(ptr, prop) && RNA_property_editable_flag(ptr, prop)) {
- override_status |= RNA_OVERRIDE_STATUS_OVERRIDABLE;
- }
-
- IDOverrideLibraryPropertyOperation *opop = RNA_property_override_property_operation_find(
- ptr, prop, index, false, NULL);
- if (opop != NULL) {
- override_status |= RNA_OVERRIDE_STATUS_OVERRIDDEN;
- if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_MANDATORY) {
- override_status |= RNA_OVERRIDE_STATUS_MANDATORY;
- }
- if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_LOCKED) {
- override_status |= RNA_OVERRIDE_STATUS_LOCKED;
- }
- }
-
- return override_status;
-}
-
bool RNA_path_resolved_create(PointerRNA *ptr,
struct PropertyRNA *prop,
const int prop_index,
diff --git a/source/blender/makesrna/intern/rna_access_compare_override.c b/source/blender/makesrna/intern/rna_access_compare_override.c
new file mode 100644
index 00000000000..b0a83ea38c6
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_access_compare_override.c
@@ -0,0 +1,1099 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup RNA
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_constraint_types.h"
+#include "DNA_modifier_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+
+#ifdef DEBUG_OVERRIDE_TIMEIT
+# include "PIL_time_utildefines.h"
+#endif
+
+#include "BKE_idprop.h"
+#include "BKE_library_override.h"
+#include "BKE_main.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "rna_internal.h"
+#include "rna_access_internal.h"
+
+int RNA_property_override_flag(PropertyRNA *prop)
+{
+ return rna_ensure_property(prop)->flag_override;
+}
+
+/** \note Does not take into account editable status, this has to be checked separately
+ * (using #RNA_property_editable_flag() usually). */
+bool RNA_property_overridable_get(PointerRNA *ptr, PropertyRNA *prop)
+{
+ if (prop->magic == RNA_MAGIC) {
+ /* Special handling for insertions of constraints or modifiers... */
+ /* TODO Note We may want to add a more generic system to RNA
+ * (like a special property in struct of items)
+ * if we get more overrideable collections,
+ * for now we can live with those special-cases handling I think. */
+ if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
+ bConstraint *con = ptr->data;
+ if (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) {
+ return true;
+ }
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
+ ModifierData *mod = ptr->data;
+ if (mod->flag & eModifierFlag_OverrideLibrary_Local) {
+ return true;
+ }
+ }
+ /* If this is a RNA-defined property (real or 'virtual' IDProp),
+ * we want to use RNA prop flag. */
+ return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) &&
+ (prop->flag_override & PROPOVERRIDE_OVERRIDABLE_LIBRARY);
+ }
+ else {
+ /* If this is a real 'pure' IDProp (aka custom property), we want to use the IDProp flag. */
+ return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON) &&
+ (((IDProperty *)prop)->flag & IDP_FLAG_OVERRIDABLE_LIBRARY);
+ }
+}
+
+/* Should only be used for custom properties */
+bool RNA_property_overridable_library_set(PointerRNA *UNUSED(ptr),
+ PropertyRNA *prop,
+ const bool is_overridable)
+{
+ /* Only works for pure custom properties IDProps. */
+ if (prop->magic != RNA_MAGIC) {
+ IDProperty *idprop = (IDProperty *)prop;
+
+ idprop->flag = is_overridable ? (idprop->flag | IDP_FLAG_OVERRIDABLE_LIBRARY) :
+ (idprop->flag & ~IDP_FLAG_OVERRIDABLE_LIBRARY);
+ return true;
+ }
+
+ return false;
+}
+
+bool RNA_property_overridden(PointerRNA *ptr, PropertyRNA *prop)
+{
+ char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
+ ID *id = ptr->owner_id;
+
+ if (rna_path == NULL || id == NULL || id->override_library == NULL) {
+ return false;
+ }
+
+ return (BKE_override_library_property_find(id->override_library, rna_path) != NULL);
+}
+
+bool RNA_property_comparable(PointerRNA *UNUSED(ptr), PropertyRNA *prop)
+{
+ prop = rna_ensure_property(prop);
+
+ return !(prop->flag_override & PROPOVERRIDE_NO_COMPARISON);
+}
+
+static bool rna_property_override_operation_apply(Main *bmain,
+ PointerRNA *ptr_local,
+ PointerRNA *ptr_override,
+ PointerRNA *ptr_storage,
+ PropertyRNA *prop_local,
+ PropertyRNA *prop_override,
+ PropertyRNA *prop_storage,
+ PointerRNA *ptr_item_local,
+ PointerRNA *ptr_item_override,
+ PointerRNA *ptr_item_storage,
+ IDOverrideLibraryPropertyOperation *opop);
+
+bool RNA_property_copy(
+ Main *bmain, PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index)
+{
+ if (!RNA_property_editable(ptr, prop)) {
+ return false;
+ }
+
+ PropertyRNA *prop_dst = prop;
+ PropertyRNA *prop_src = prop;
+
+ /* Ensure we get real property data,
+ * be it an actual RNA property, or an IDProperty in disguise. */
+ prop_dst = rna_ensure_property_realdata(&prop_dst, ptr);
+ prop_src = rna_ensure_property_realdata(&prop_src, fromptr);
+
+ /* IDprops: destination may not exist, if source does and is set, try to create it. */
+ /* Note: this is sort of quick hack/bandage to fix the issue,
+ * we need to rethink how IDProps are handled in 'diff' RNA code completely, imho... */
+ if (prop_src != NULL && prop_dst == NULL && RNA_property_is_set(fromptr, prop)) {
+ BLI_assert(prop_src->magic != RNA_MAGIC);
+ IDProperty *idp_dst = RNA_struct_idprops(ptr, true);
+ IDProperty *prop_idp_dst = IDP_CopyProperty((IDProperty *)prop_src);
+ IDP_AddToGroup(idp_dst, prop_idp_dst);
+ rna_idproperty_touch(prop_idp_dst);
+ /* Nothing else to do here... */
+ return true;
+ }
+
+ if (ELEM(NULL, prop_dst, prop_src)) {
+ return false;
+ }
+
+ IDOverrideLibraryPropertyOperation opop = {
+ .operation = IDOVERRIDE_LIBRARY_OP_REPLACE,
+ .subitem_reference_index = index,
+ .subitem_local_index = index,
+ };
+ return rna_property_override_operation_apply(
+ bmain, ptr, fromptr, NULL, prop_dst, prop_src, NULL, NULL, NULL, NULL, &opop);
+}
+
+static int rna_property_override_diff(Main *bmain,
+ PointerRNA *ptr_a,
+ PointerRNA *ptr_b,
+ PropertyRNA *prop,
+ PropertyRNA *prop_a,
+ PropertyRNA *prop_b,
+ const char *rna_path,
+ eRNACompareMode mode,
+ IDOverrideLibrary *override,
+ const int flags,
+ eRNAOverrideMatchResult *r_report_flags);
+
+bool RNA_property_equals(
+ Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, PropertyRNA *prop, eRNACompareMode mode)
+{
+ BLI_assert(ELEM(mode, RNA_EQ_STRICT, RNA_EQ_UNSET_MATCH_ANY, RNA_EQ_UNSET_MATCH_NONE));
+
+ return (rna_property_override_diff(
+ bmain, ptr_a, ptr_b, prop, NULL, NULL, NULL, mode, NULL, 0, NULL) == 0);
+}
+
+bool RNA_struct_equals(Main *bmain, PointerRNA *ptr_a, PointerRNA *ptr_b, eRNACompareMode mode)
+{
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop;
+ bool equals = true;
+
+ if (ptr_a == NULL && ptr_b == NULL) {
+ return true;
+ }
+ else if (ptr_a == NULL || ptr_b == NULL) {
+ return false;
+ }
+ else if (ptr_a->type != ptr_b->type) {
+ return false;
+ }
+
+ iterprop = RNA_struct_iterator_property(ptr_a->type);
+
+ RNA_property_collection_begin(ptr_a, iterprop, &iter);
+ for (; iter.valid; RNA_property_collection_next(&iter)) {
+ PropertyRNA *prop = iter.ptr.data;
+
+ if (!RNA_property_equals(bmain, ptr_a, ptr_b, prop, mode)) {
+ equals = false;
+ break;
+ }
+ }
+ RNA_property_collection_end(&iter);
+
+ return equals;
+}
+
+/* Low-level functions, also used by non-override RNA API like copy or equality check. */
+
+/** Generic RNA property diff function.
+ *
+ * \note about \a prop and \a prop_a/prop_b parameters:
+ * the former is expected to be an 'un-resolved' one,
+ * while the two later are expected to be fully resolved ones
+ * (i.e. to be the IDProps when they should be, etc.).
+ * When \a prop is given, \a prop_a and \a prop_b should always be NULL, and vice-versa.
+ * This is necessary, because we cannot perform 'set/unset' checks on resolved properties
+ * (unset IDProps would merely be NULL then).
+ *
+ * \note When there is no equality,
+ * but we cannot determine an order (greater than/lesser than), we return 1.
+ */
+static int rna_property_override_diff(Main *bmain,
+ PointerRNA *ptr_a,
+ PointerRNA *ptr_b,
+ PropertyRNA *prop,
+ PropertyRNA *prop_a,
+ PropertyRNA *prop_b,
+ const char *rna_path,
+ eRNACompareMode mode,
+ IDOverrideLibrary *override,
+ const int flags,
+ eRNAOverrideMatchResult *r_report_flags)
+{
+ if (prop != NULL) {
+ BLI_assert(prop_a == NULL && prop_b == NULL);
+ prop_a = prop;
+ prop_b = prop;
+ }
+
+ if (ELEM(NULL, prop_a, prop_b)) {
+ return (prop_a == prop_b) ? 0 : 1;
+ }
+
+ if (!RNA_property_comparable(ptr_a, prop_a) || !RNA_property_comparable(ptr_b, prop_b)) {
+ return 0;
+ }
+
+ if (mode == RNA_EQ_UNSET_MATCH_ANY) {
+ /* uninitialized properties are assumed to match anything */
+ if (!RNA_property_is_set(ptr_a, prop_a) || !RNA_property_is_set(ptr_b, prop_b)) {
+ return 0;
+ }
+ }
+ else if (mode == RNA_EQ_UNSET_MATCH_NONE) {
+ /* unset properties never match set properties */
+ if (RNA_property_is_set(ptr_a, prop_a) != RNA_property_is_set(ptr_b, prop_b)) {
+ return 1;
+ }
+ }
+
+ if (prop != NULL) {
+ /* Ensure we get real property data, be it an actual RNA property,
+ * or an IDProperty in disguise. */
+ prop_a = rna_ensure_property_realdata(&prop_a, ptr_a);
+ prop_b = rna_ensure_property_realdata(&prop_b, ptr_b);
+
+ if (ELEM(NULL, prop_a, prop_b)) {
+ return (prop_a == prop_b) ? 0 : 1;
+ }
+ }
+
+ /* Check if we are working with arrays. */
+ const bool is_array_a = RNA_property_array_check(prop_a);
+ const bool is_array_b = RNA_property_array_check(prop_b);
+
+ if (is_array_a != is_array_b) {
+ /* Should probably never happen actually... */
+ BLI_assert(0);
+ return is_array_a ? 1 : -1;
+ }
+
+ /* Get the length of the array to work with. */
+ const int len_a = RNA_property_array_length(ptr_a, prop_a);
+ const int len_b = RNA_property_array_length(ptr_b, prop_b);
+
+ if (len_a != len_b) {
+ /* Do not handle override in that case,
+ * we do not support insertion/deletion from arrays for now. */
+ return len_a > len_b ? 1 : -1;
+ }
+
+ if (is_array_a && len_a == 0) {
+ /* Empty arrays, will happen in some case with dynamic ones. */
+ return 0;
+ }
+
+ RNAPropOverrideDiff override_diff = NULL;
+ /* Special case for IDProps, we use default callback then. */
+ if (prop_a->magic != RNA_MAGIC) {
+ override_diff = rna_property_override_diff_default;
+ if (prop_b->magic == RNA_MAGIC && prop_b->override_diff != override_diff) {
+ override_diff = NULL;
+ }
+ }
+ else if (prop_b->magic != RNA_MAGIC) {
+ override_diff = rna_property_override_diff_default;
+ if (prop_a->override_diff != override_diff) {
+ override_diff = NULL;
+ }
+ }
+ else if (prop_a->override_diff == prop_b->override_diff) {
+ override_diff = prop_a->override_diff;
+ }
+
+ if (override_diff == NULL) {
+#ifndef NDEBUG
+ printf("'%s' gives unmatching or NULL RNA diff callbacks, should not happen (%d vs. %d).\n",
+ rna_path ?
+ rna_path :
+ (prop_a->magic != RNA_MAGIC ? ((IDProperty *)prop_a)->name : prop_a->identifier),
+ prop_a->magic == RNA_MAGIC,
+ prop_b->magic == RNA_MAGIC);
+#endif
+ BLI_assert(0);
+ return 1;
+ }
+
+ bool override_changed = false;
+ int diff_flags = flags;
+ if (!RNA_property_overridable_get(ptr_a, prop_a)) {
+ diff_flags &= ~RNA_OVERRIDE_COMPARE_CREATE;
+ }
+ const int diff = override_diff(bmain,
+ ptr_a,
+ ptr_b,
+ prop_a,
+ prop_b,
+ len_a,
+ len_b,
+ mode,
+ override,
+ rna_path,
+ diff_flags,
+ &override_changed);
+ if (override_changed && r_report_flags) {
+ *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_CREATED;
+ }
+
+ return diff;
+}
+
+/* Modify local data-block to make it ready for override application
+ * (only needed for diff operations, where we use
+ * the local data-block's data as second operand). */
+static bool rna_property_override_operation_store(Main *bmain,
+ PointerRNA *ptr_local,
+ PointerRNA *ptr_reference,
+ PointerRNA *ptr_storage,
+ PropertyRNA *prop_local,
+ PropertyRNA *prop_reference,
+ PropertyRNA *prop_storage,
+ IDOverrideLibraryProperty *op)
+{
+ int len_local, len_reference, len_storage = 0;
+ bool changed = false;
+
+ if (ptr_storage == NULL) {
+ return changed;
+ }
+
+ /* get the length of the array to work with */
+ len_local = RNA_property_array_length(ptr_local, prop_local);
+ len_reference = RNA_property_array_length(ptr_reference, prop_reference);
+ if (prop_storage) {
+ len_storage = RNA_property_array_length(ptr_storage, prop_storage);
+ }
+
+ if (len_local != len_reference || len_local != len_storage) {
+ /* Do not handle override in that case,
+ * we do not support insertion/deletion from arrays for now. */
+ return changed;
+ }
+
+ BLI_assert(prop_local->override_store == prop_reference->override_store &&
+ (!ptr_storage || prop_local->override_store == prop_storage->override_store) &&
+ prop_local->override_store != NULL);
+
+ for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+ /* Only needed for diff operations. */
+ if (!ELEM(opop->operation,
+ IDOVERRIDE_LIBRARY_OP_ADD,
+ IDOVERRIDE_LIBRARY_OP_SUBTRACT,
+ IDOVERRIDE_LIBRARY_OP_MULTIPLY)) {
+ continue;
+ }
+
+ if (prop_local->override_store(bmain,
+ ptr_local,
+ ptr_reference,
+ ptr_storage,
+ prop_local,
+ prop_reference,
+ prop_storage,
+ len_local,
+ len_reference,
+ len_storage,
+ opop)) {
+ changed = true;
+ }
+ }
+
+ return changed;
+}
+
+static bool rna_property_override_operation_apply(Main *bmain,
+ PointerRNA *ptr_dst,
+ PointerRNA *ptr_src,
+ PointerRNA *ptr_storage,
+ PropertyRNA *prop_dst,
+ PropertyRNA *prop_src,
+ PropertyRNA *prop_storage,
+ PointerRNA *ptr_item_dst,
+ PointerRNA *ptr_item_src,
+ PointerRNA *ptr_item_storage,
+ IDOverrideLibraryPropertyOperation *opop)
+{
+ int len_dst, len_src, len_storage = 0;
+
+ const short override_op = opop->operation;
+
+ if (override_op == IDOVERRIDE_LIBRARY_OP_NOOP) {
+ return true;
+ }
+
+ if (ELEM(override_op,
+ IDOVERRIDE_LIBRARY_OP_ADD,
+ IDOVERRIDE_LIBRARY_OP_SUBTRACT,
+ IDOVERRIDE_LIBRARY_OP_MULTIPLY) &&
+ !ptr_storage) {
+ /* We cannot apply 'diff' override operations without some reference storage.
+ * This should typically only happen at read time of .blend file... */
+ return false;
+ }
+
+ if (ELEM(override_op,
+ IDOVERRIDE_LIBRARY_OP_ADD,
+ IDOVERRIDE_LIBRARY_OP_SUBTRACT,
+ IDOVERRIDE_LIBRARY_OP_MULTIPLY) &&
+ !prop_storage) {
+ /* We cannot apply 'diff' override operations without some reference storage.
+ * This should typically only happen at read time of .blend file... */
+ return false;
+ }
+
+ RNAPropOverrideApply override_apply = NULL;
+ /* Special case for IDProps, we use default callback then. */
+ if (prop_dst->magic != RNA_MAGIC) {
+ override_apply = rna_property_override_apply_default;
+ if (prop_src->magic == RNA_MAGIC && prop_src->override_apply != override_apply) {
+ override_apply = NULL;
+ }
+ }
+ else if (prop_src->magic != RNA_MAGIC) {
+ override_apply = rna_property_override_apply_default;
+ if (prop_dst->override_apply != override_apply) {
+ override_apply = NULL;
+ }
+ }
+ else if (prop_dst->override_apply == prop_src->override_apply) {
+ override_apply = prop_dst->override_apply;
+ }
+
+ if (ptr_storage && prop_storage->magic == RNA_MAGIC &&
+ prop_storage->override_apply != override_apply) {
+ override_apply = NULL;
+ }
+
+ if (override_apply == NULL) {
+#ifndef NDEBUG
+ printf("'%s' gives unmatching or NULL RNA copy callbacks, should not happen (%d vs. %d).\n",
+ prop_dst->magic != RNA_MAGIC ? ((IDProperty *)prop_dst)->name : prop_dst->identifier,
+ prop_dst->magic == RNA_MAGIC,
+ prop_src->magic == RNA_MAGIC);
+#endif
+ BLI_assert(0);
+ return false;
+ }
+
+ /* get the length of the array to work with */
+ len_dst = RNA_property_array_length(ptr_dst, prop_dst);
+ len_src = RNA_property_array_length(ptr_src, prop_src);
+ if (ptr_storage) {
+ len_storage = RNA_property_array_length(ptr_storage, prop_storage);
+ }
+
+ if (len_dst != len_src || (ptr_storage && len_dst != len_storage)) {
+ /* Do not handle override in that case,
+ * we do not support insertion/deletion from arrays for now. */
+ return false;
+ }
+
+ /* get and set the default values as appropriate for the various types */
+ return override_apply(bmain,
+ ptr_dst,
+ ptr_src,
+ ptr_storage,
+ prop_dst,
+ prop_src,
+ prop_storage,
+ len_dst,
+ len_src,
+ len_storage,
+ ptr_item_dst,
+ ptr_item_src,
+ ptr_item_storage,
+ opop);
+}
+
+/**
+ * Check whether reference and local overridden data match (are the same),
+ * with respect to given restrictive sets of properties.
+ * If requested, will generate needed new property overrides, and/or restore values from reference.
+ *
+ * \param r_report_flags: If given,
+ * will be set with flags matching actions taken by the function on \a ptr_local.
+ *
+ * \return True if _resulting_ \a ptr_local does match \a ptr_reference.
+ */
+bool RNA_struct_override_matches(Main *bmain,
+ PointerRNA *ptr_local,
+ PointerRNA *ptr_reference,
+ const char *root_path,
+ IDOverrideLibrary *override,
+ const eRNAOverrideMatch flags,
+ eRNAOverrideMatchResult *r_report_flags)
+{
+ CollectionPropertyIterator iter;
+ PropertyRNA *iterprop;
+ bool matching = true;
+
+ BLI_assert(ptr_local->type == ptr_reference->type);
+ BLI_assert(ptr_local->owner_id && ptr_reference->owner_id);
+
+ const bool ignore_non_overridable = (flags & RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE) != 0;
+ const bool ignore_overridden = (flags & RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN) != 0;
+ const bool do_create = (flags & RNA_OVERRIDE_COMPARE_CREATE) != 0;
+ const bool do_restore = (flags & RNA_OVERRIDE_COMPARE_RESTORE) != 0;
+
+//#define DEBUG_OVERRIDE_TIMEIT
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ static float _sum_time_global = 0.0f;
+ static float _num_time_global = 0.0f;
+ double _timeit_time_global;
+ static float _sum_time_diffing = 0.0f;
+ static float _delta_time_diffing = 0.0f;
+ static int _num_delta_time_diffing = 0.0f;
+ static float _num_time_diffing = 0.0f;
+ double _timeit_time_diffing;
+
+ if (!root_path) {
+ _delta_time_diffing = 0.0f;
+ _num_delta_time_diffing = 0;
+ _timeit_time_global = PIL_check_seconds_timer();
+ }
+#endif
+
+ iterprop = RNA_struct_iterator_property(ptr_local->type);
+
+ for (RNA_property_collection_begin(ptr_local, iterprop, &iter); iter.valid;
+ RNA_property_collection_next(&iter)) {
+ PropertyRNA *prop_local = iter.ptr.data;
+ PropertyRNA *prop_reference = iter.ptr.data;
+
+ /* Ensure we get real property data, be it an actual RNA property,
+ * or an IDProperty in disguise. */
+ prop_local = rna_ensure_property_realdata(&prop_local, ptr_local);
+ prop_reference = rna_ensure_property_realdata(&prop_reference, ptr_reference);
+
+ if (ELEM(NULL, prop_local, prop_reference)) {
+ continue;
+ }
+
+ if (ignore_non_overridable && !RNA_property_overridable_get(ptr_local, prop_local)) {
+ continue;
+ }
+
+#if 0 /* This actually makes things slower, since it has to check for animation paths etc! */
+ if (RNA_property_animated(ptr_local, prop_local)) {
+ /* We cannot do anything here really, animation is some kind of dynamic overrides that has
+ * precedence over static one... */
+ continue;
+ }
+#endif
+
+#define RNA_PATH_BUFFSIZE 8192
+#define RNA_PATH_PRINTF(_str, ...) \
+ if (BLI_snprintf(rna_path, RNA_PATH_BUFFSIZE, (_str), __VA_ARGS__) >= RNA_PATH_BUFFSIZE) { \
+ rna_path = BLI_sprintfN((_str), __VA_ARGS__); \
+ } \
+ (void)0
+#define RNA_PATH_FREE \
+ if (rna_path != rna_path_buffer) \
+ MEM_freeN(rna_path)
+
+ char rna_path_buffer[RNA_PATH_BUFFSIZE];
+ char *rna_path = rna_path_buffer;
+
+ /* XXX TODO this will have to be refined to handle collections insertions, and array items */
+ if (root_path) {
+ /* Inlined building, much much more efficient. */
+ if (prop_local->magic == RNA_MAGIC) {
+ RNA_PATH_PRINTF("%s.%s", root_path, RNA_property_identifier(prop_local));
+ }
+ else {
+ RNA_PATH_PRINTF("%s[\"%s\"]", root_path, RNA_property_identifier(prop_local));
+ }
+ }
+ else {
+ /* This is rather slow, but is not much called, so not really worth optimizing. */
+ rna_path = RNA_path_from_ID_to_property(ptr_local, prop_local);
+ }
+ if (rna_path == NULL) {
+ continue;
+ }
+
+ // printf("Override Checking %s\n", rna_path);
+
+ if (ignore_overridden && BKE_override_library_property_find(override, rna_path) != NULL) {
+ RNA_PATH_FREE;
+ continue;
+ }
+
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ if (!root_path) {
+ _timeit_time_diffing = PIL_check_seconds_timer();
+ }
+#endif
+
+ eRNAOverrideMatchResult report_flags = 0;
+ const int diff = rna_property_override_diff(bmain,
+ ptr_local,
+ ptr_reference,
+ NULL,
+ prop_local,
+ prop_reference,
+ rna_path,
+ RNA_EQ_STRICT,
+ override,
+ flags,
+ &report_flags);
+
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ if (!root_path) {
+ const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_diffing);
+ _delta_time_diffing += _delta_time;
+ _num_delta_time_diffing++;
+ }
+#endif
+
+ matching = matching && diff == 0;
+ if (r_report_flags) {
+ *r_report_flags |= report_flags;
+ }
+
+ if (diff != 0) {
+ /* XXX TODO: refine this for per-item overriding of arrays... */
+ IDOverrideLibraryProperty *op = BKE_override_library_property_find(override, rna_path);
+ IDOverrideLibraryPropertyOperation *opop = op ? op->operations.first : NULL;
+
+ if (do_restore && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0) {
+ /* We are allowed to restore to reference's values. */
+ if (ELEM(NULL, op, opop) || opop->operation == IDOVERRIDE_LIBRARY_OP_NOOP) {
+ /* We should restore that property to its reference value */
+ if (RNA_property_editable(ptr_local, prop_local)) {
+ IDOverrideLibraryPropertyOperation opop_tmp = {
+ .operation = IDOVERRIDE_LIBRARY_OP_REPLACE,
+ .subitem_reference_index = -1,
+ .subitem_local_index = -1,
+ };
+ rna_property_override_operation_apply(bmain,
+ ptr_local,
+ ptr_reference,
+ NULL,
+ prop_local,
+ prop_reference,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &opop_tmp);
+ if (r_report_flags) {
+ *r_report_flags |= RNA_OVERRIDE_MATCH_RESULT_RESTORED;
+ }
+ }
+ else {
+ /* Too noisy for now, this triggers on runtime props like transform matrices etc. */
+#if 0
+ BLI_assert(!"We have differences between reference and "
+ "overriding data on non-editable property.");
+#endif
+ matching = false;
+ }
+ }
+ }
+ else if ((report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) == 0 && ELEM(NULL, op, opop)) {
+ /* This property is not overridden, and differs from reference, so we have no match. */
+ matching = false;
+ if (!(do_create || do_restore)) {
+ /* Since we have no 'changing' action allowed, we can break here. */
+ MEM_SAFE_FREE(rna_path);
+ break;
+ }
+ }
+ }
+
+ RNA_PATH_FREE;
+
+#undef RNA_PATH_BUFFSIZE
+#undef RNA_PATH_PRINTF
+#undef RNA_PATH_FREE
+ }
+ RNA_property_collection_end(&iter);
+
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ if (!root_path) {
+ const float _delta_time = (float)(PIL_check_seconds_timer() - _timeit_time_global);
+ _sum_time_global += _delta_time;
+ _num_time_global++;
+ _sum_time_diffing += _delta_time_diffing;
+ _num_time_diffing++;
+ printf("ID: %s\n", ((ID *)ptr_local->owner_id)->name);
+ printf("time end (%s): %.6f\n", __func__, _delta_time);
+ printf("time averaged (%s): %.6f (total: %.6f, in %d runs)\n",
+ __func__,
+ (_sum_time_global / _num_time_global),
+ _sum_time_global,
+ (int)_num_time_global);
+ printf("diffing time end (%s): %.6f (in %d runs)\n",
+ __func__,
+ _delta_time_diffing,
+ _num_delta_time_diffing);
+ printf("diffing time averaged (%s): %.6f (total: %.6f, in %d runs)\n",
+ __func__,
+ (_sum_time_diffing / _num_time_diffing),
+ _sum_time_diffing,
+ (int)_num_time_diffing);
+ }
+#endif
+
+ return matching;
+}
+
+/** Store needed second operands into \a storage data-block
+ * for differential override operations. */
+bool RNA_struct_override_store(Main *bmain,
+ PointerRNA *ptr_local,
+ PointerRNA *ptr_reference,
+ PointerRNA *ptr_storage,
+ IDOverrideLibrary *override)
+{
+ bool changed = false;
+
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_START_AVERAGED(RNA_struct_override_store);
+#endif
+ for (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) {
+ /* Simplified for now! */
+ PointerRNA data_reference, data_local;
+ PropertyRNA *prop_reference, *prop_local;
+
+ if (RNA_path_resolve_property(ptr_local, op->rna_path, &data_local, &prop_local) &&
+ RNA_path_resolve_property(ptr_reference, op->rna_path, &data_reference, &prop_reference)) {
+ PointerRNA data_storage;
+ PropertyRNA *prop_storage = NULL;
+
+ /* It is totally OK if this does not success,
+ * only a subset of override operations actually need storage. */
+ if (ptr_storage && (ptr_storage->owner_id != NULL)) {
+ RNA_path_resolve_property(ptr_storage, op->rna_path, &data_storage, &prop_storage);
+ }
+
+ if (rna_property_override_operation_store(bmain,
+ &data_local,
+ &data_reference,
+ &data_storage,
+ prop_reference,
+ prop_local,
+ prop_storage,
+ op)) {
+ changed = true;
+ }
+ }
+ }
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_END_AVERAGED(RNA_struct_override_store);
+#endif
+
+ return changed;
+}
+
+static void rna_property_override_apply_ex(Main *bmain,
+ PointerRNA *ptr_dst,
+ PointerRNA *ptr_src,
+ PointerRNA *ptr_storage,
+ PropertyRNA *prop_dst,
+ PropertyRNA *prop_src,
+ PropertyRNA *prop_storage,
+ PointerRNA *ptr_item_dst,
+ PointerRNA *ptr_item_src,
+ PointerRNA *ptr_item_storage,
+ IDOverrideLibraryProperty *op,
+ const bool do_insert)
+{
+ for (IDOverrideLibraryPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+ if (!do_insert != !ELEM(opop->operation,
+ IDOVERRIDE_LIBRARY_OP_INSERT_AFTER,
+ IDOVERRIDE_LIBRARY_OP_INSERT_BEFORE)) {
+ if (!do_insert) {
+ printf("Skipping insert override operations in first pass (%s)!\n", op->rna_path);
+ }
+ continue;
+ }
+
+ /* Note: will have to think about putting that logic into its own function maybe?
+ * Would be nice to have it in a single place...
+ * Note that here, src is the local saved ID, and dst is a copy of the linked ID (since we use
+ * local ID as storage to apply local changes on top of a clean copy of the linked data). */
+ PointerRNA private_ptr_item_dst, private_ptr_item_src, private_ptr_item_storage;
+ if (opop->subitem_local_name != NULL || opop->subitem_reference_name != NULL ||
+ opop->subitem_local_index != -1 || opop->subitem_reference_index != -1) {
+ RNA_POINTER_INVALIDATE(&private_ptr_item_dst);
+ RNA_POINTER_INVALIDATE(&private_ptr_item_src);
+ RNA_POINTER_INVALIDATE(&private_ptr_item_storage);
+ if (opop->subitem_local_name != NULL) {
+ RNA_property_collection_lookup_string(
+ ptr_src, prop_src, opop->subitem_local_name, &private_ptr_item_src);
+ if (opop->subitem_reference_name != NULL) {
+ RNA_property_collection_lookup_string(
+ ptr_dst, prop_dst, opop->subitem_reference_name, &private_ptr_item_dst);
+ }
+ else {
+ RNA_property_collection_lookup_string(
+ ptr_dst, prop_dst, opop->subitem_local_name, &private_ptr_item_dst);
+ }
+ }
+ else if (opop->subitem_reference_name != NULL) {
+ RNA_property_collection_lookup_string(
+ ptr_src, prop_src, opop->subitem_reference_name, &private_ptr_item_src);
+ RNA_property_collection_lookup_string(
+ ptr_dst, prop_dst, opop->subitem_reference_name, &private_ptr_item_dst);
+ }
+ else if (opop->subitem_local_index != -1) {
+ RNA_property_collection_lookup_int(
+ ptr_src, prop_src, opop->subitem_local_index, &private_ptr_item_src);
+ if (opop->subitem_reference_index != -1) {
+ RNA_property_collection_lookup_int(
+ ptr_dst, prop_dst, opop->subitem_reference_index, &private_ptr_item_dst);
+ }
+ else {
+ RNA_property_collection_lookup_int(
+ ptr_dst, prop_dst, opop->subitem_local_index, &private_ptr_item_dst);
+ }
+ }
+ else if (opop->subitem_reference_index != -1) {
+ RNA_property_collection_lookup_int(
+ ptr_src, prop_src, opop->subitem_reference_index, &private_ptr_item_src);
+ RNA_property_collection_lookup_int(
+ ptr_dst, prop_dst, opop->subitem_reference_index, &private_ptr_item_dst);
+ }
+ if (prop_storage != NULL) {
+ if (opop->subitem_local_name != NULL) {
+ RNA_property_collection_lookup_string(
+ ptr_storage, prop_storage, opop->subitem_local_name, &private_ptr_item_storage);
+ }
+ else if (opop->subitem_reference_name != NULL) {
+ RNA_property_collection_lookup_string(
+ ptr_storage, prop_storage, opop->subitem_reference_name, &private_ptr_item_storage);
+ }
+ else if (opop->subitem_local_index != -1) {
+ RNA_property_collection_lookup_int(
+ ptr_storage, prop_storage, opop->subitem_local_index, &private_ptr_item_storage);
+ }
+ else if (opop->subitem_reference_index != -1) {
+ RNA_property_collection_lookup_int(
+ ptr_storage, prop_storage, opop->subitem_reference_index, &private_ptr_item_storage);
+ }
+ }
+ ptr_item_dst = &private_ptr_item_dst;
+ ptr_item_src = &private_ptr_item_src;
+ ptr_item_storage = &private_ptr_item_storage;
+ }
+
+ if (!rna_property_override_operation_apply(bmain,
+ ptr_dst,
+ ptr_src,
+ ptr_storage,
+ prop_dst,
+ prop_src,
+ prop_storage,
+ ptr_item_dst,
+ ptr_item_src,
+ ptr_item_storage,
+ opop)) {
+ /* TODO No assert here, would be much much better to just report as warning,
+ * failing override applications will probably be fairly common! */
+ BLI_assert(0);
+ }
+ }
+}
+
+/** Apply given \a override operations on \a ptr_dst, using \a ptr_src
+ * (and \a ptr_storage for differential ops) as source. */
+void RNA_struct_override_apply(Main *bmain,
+ PointerRNA *ptr_dst,
+ PointerRNA *ptr_src,
+ PointerRNA *ptr_storage,
+ IDOverrideLibrary *override)
+{
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_START_AVERAGED(RNA_struct_override_apply);
+#endif
+ /* Note: Applying insert operations in a separate pass is mandatory.
+ * We could optimize this later, but for now, as inefficient as it is,
+ * don't think this is a critical point.
+ */
+ bool do_insert = false;
+ for (int i = 0; i < 2; i++, do_insert = true) {
+ for (IDOverrideLibraryProperty *op = override->properties.first; op; op = op->next) {
+ /* Simplified for now! */
+ PointerRNA data_src, data_dst;
+ PointerRNA data_item_src, data_item_dst;
+ PropertyRNA *prop_src, *prop_dst;
+
+ if (RNA_path_resolve_property_and_item_pointer(
+ ptr_dst, op->rna_path, &data_dst, &prop_dst, &data_item_dst) &&
+ RNA_path_resolve_property_and_item_pointer(
+ ptr_src, op->rna_path, &data_src, &prop_src, &data_item_src)) {
+ PointerRNA data_storage, data_item_storage;
+ PropertyRNA *prop_storage = NULL;
+
+ /* It is totally OK if this does not success,
+ * only a subset of override operations actually need storage. */
+ if (ptr_storage && (ptr_storage->owner_id != NULL)) {
+ RNA_path_resolve_property_and_item_pointer(
+ ptr_storage, op->rna_path, &data_storage, &prop_storage, &data_item_storage);
+ }
+
+ rna_property_override_apply_ex(bmain,
+ &data_dst,
+ &data_src,
+ prop_storage ? &data_storage : NULL,
+ prop_dst,
+ prop_src,
+ prop_storage,
+ &data_item_dst,
+ &data_item_src,
+ prop_storage ? &data_item_storage : NULL,
+ op,
+ do_insert);
+ }
+#ifndef NDEBUG
+ else {
+ printf(
+ "Failed to apply library override operation to '%s.%s' "
+ "(could not resolve some properties, local: %d, override: %d)\n",
+ ((ID *)ptr_src->owner_id)->name,
+ op->rna_path,
+ RNA_path_resolve_property(ptr_dst, op->rna_path, &data_dst, &prop_dst),
+ RNA_path_resolve_property(ptr_src, op->rna_path, &data_src, &prop_src));
+ }
+#endif
+ }
+ }
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_END_AVERAGED(RNA_struct_override_apply);
+#endif
+}
+
+IDOverrideLibraryProperty *RNA_property_override_property_find(PointerRNA *ptr, PropertyRNA *prop)
+{
+ ID *id = ptr->owner_id;
+
+ if (!id || !id->override_library) {
+ return NULL;
+ }
+
+ char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
+ if (rna_path) {
+ IDOverrideLibraryProperty *op = BKE_override_library_property_find(id->override_library,
+ rna_path);
+ MEM_freeN(rna_path);
+ return op;
+ }
+ return NULL;
+}
+
+IDOverrideLibraryProperty *RNA_property_override_property_get(PointerRNA *ptr,
+ PropertyRNA *prop,
+ bool *r_created)
+{
+ ID *id = ptr->owner_id;
+
+ if (!id || !id->override_library) {
+ return NULL;
+ }
+
+ char *rna_path = RNA_path_from_ID_to_property(ptr, prop);
+ if (rna_path) {
+ IDOverrideLibraryProperty *op = BKE_override_library_property_get(
+ id->override_library, rna_path, r_created);
+ MEM_freeN(rna_path);
+ return op;
+ }
+ return NULL;
+}
+
+IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_find(
+ PointerRNA *ptr, PropertyRNA *prop, const int index, const bool strict, bool *r_strict)
+{
+ IDOverrideLibraryProperty *op = RNA_property_override_property_find(ptr, prop);
+
+ if (!op) {
+ return NULL;
+ }
+
+ return BKE_override_library_property_operation_find(
+ op, NULL, NULL, index, index, strict, r_strict);
+}
+
+IDOverrideLibraryPropertyOperation *RNA_property_override_property_operation_get(
+ PointerRNA *ptr,
+ PropertyRNA *prop,
+ const short operation,
+ const int index,
+ const bool strict,
+ bool *r_strict,
+ bool *r_created)
+{
+ IDOverrideLibraryProperty *op = RNA_property_override_property_get(ptr, prop, NULL);
+
+ if (!op) {
+ return NULL;
+ }
+
+ return BKE_override_library_property_operation_get(
+ op, operation, NULL, NULL, index, index, strict, r_strict, r_created);
+}
+
+eRNAOverrideStatus RNA_property_override_library_status(PointerRNA *ptr,
+ PropertyRNA *prop,
+ const int index)
+{
+ int override_status = 0;
+
+ if (!BKE_override_library_is_enabled()) {
+ return override_status;
+ }
+
+ if (!ptr || !prop || !ptr->owner_id || !(ptr->owner_id)->override_library) {
+ return override_status;
+ }
+
+ if (RNA_property_overridable_get(ptr, prop) && RNA_property_editable_flag(ptr, prop)) {
+ override_status |= RNA_OVERRIDE_STATUS_OVERRIDABLE;
+ }
+
+ IDOverrideLibraryPropertyOperation *opop = RNA_property_override_property_operation_find(
+ ptr, prop, index, false, NULL);
+ if (opop != NULL) {
+ override_status |= RNA_OVERRIDE_STATUS_OVERRIDDEN;
+ if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_MANDATORY) {
+ override_status |= RNA_OVERRIDE_STATUS_MANDATORY;
+ }
+ if (opop->flag & IDOVERRIDE_LIBRARY_FLAG_LOCKED) {
+ override_status |= RNA_OVERRIDE_STATUS_LOCKED;
+ }
+ }
+
+ return override_status;
+}
diff --git a/source/blender/makesrna/intern/rna_access_internal.h b/source/blender/makesrna/intern/rna_access_internal.h
new file mode 100644
index 00000000000..28ec504e376
--- /dev/null
+++ b/source/blender/makesrna/intern/rna_access_internal.h
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/** \file
+ * \ingroup RNA
+ */
+
+#ifndef __RNA_ACCESS_INTERNAL_H__
+#define __RNA_ACCESS_INTERNAL_H__
+
+#include "BLI_utildefines.h"
+
+#include "rna_internal_types.h"
+
+struct IDProperty;
+
+PropertyRNA *rna_ensure_property(PropertyRNA *prop);
+
+void rna_idproperty_touch(struct IDProperty *idprop);
+
+#endif /* __ACCESS_RNA_INTERNAL_H__ */
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index 4ad2aa55c75..24f8d5c4e3d 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -249,15 +249,15 @@ static void rna_Action_active_pose_marker_index_range(
static void rna_Action_frame_range_get(PointerRNA *ptr, float *values)
{ /* don't include modifiers because they too easily can have very large
* ranges: MINAFRAMEF to MAXFRAMEF. */
- calc_action_range(ptr->id.data, values, values + 1, false);
+ calc_action_range((bAction *)ptr->owner_id, values, values + 1, false);
}
/* Used to check if an action (value pointer)
* is suitable to be assigned to the ID-block that is ptr. */
bool rna_Action_id_poll(PointerRNA *ptr, PointerRNA value)
{
- ID *srcId = (ID *)ptr->id.data;
- bAction *act = (bAction *)value.id.data;
+ ID *srcId = ptr->owner_id;
+ bAction *act = (bAction *)value.owner_id;
if (act) {
/* there can still be actions that will have undefined id-root
@@ -280,7 +280,7 @@ bool rna_Action_id_poll(PointerRNA *ptr, PointerRNA value)
bool rna_Action_actedit_assign_poll(PointerRNA *ptr, PointerRNA value)
{
SpaceAction *saction = (SpaceAction *)ptr->data;
- bAction *act = (bAction *)value.id.data;
+ bAction *act = (bAction *)value.owner_id;
if (act) {
/* there can still be actions that will have undefined id-root
diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c
index 3d14616bcc9..6157ec41f19 100644
--- a/source/blender/makesrna/intern/rna_animation.c
+++ b/source/blender/makesrna/intern/rna_animation.c
@@ -128,7 +128,7 @@ const EnumPropertyItem rna_enum_keying_flag_items_api[] = {
static void rna_AnimData_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
ANIM_id_update(bmain, id);
}
@@ -157,7 +157,7 @@ static void rna_AnimData_action_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- ID *ownerId = (ID *)ptr->id.data;
+ ID *ownerId = ptr->owner_id;
/* set action */
BKE_animdata_set_action(NULL, ownerId, value.data);
@@ -303,7 +303,7 @@ static StructRNA *rna_KeyingSetInfo_register(Main *bmain,
{
KeyingSetInfo dummyksi = {NULL};
KeyingSetInfo *ksi;
- PointerRNA dummyptr = {{NULL}};
+ PointerRNA dummyptr = {NULL};
int have_function[3];
/* setup dummy type info to store static properties in */
@@ -727,12 +727,12 @@ bool rna_AnimaData_override_apply(Main *UNUSED(bmain),
if (adt_dst == NULL && adt_src != NULL) {
/* Copy anim data from reference into final local ID. */
- BKE_animdata_copy_id(NULL, ptr_dst->id.data, ptr_src->id.data, 0);
+ BKE_animdata_copy_id(NULL, ptr_dst->owner_id, ptr_src->owner_id, 0);
return true;
}
else if (adt_dst != NULL && adt_src == NULL) {
/* Override has cleared/removed anim data from its reference. */
- BKE_animdata_free(ptr_dst->id.data, true);
+ BKE_animdata_free(ptr_dst->owner_id, true);
return true;
}
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index 59e5c584811..7949db9055f 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -50,7 +50,7 @@
static void rna_Armature_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
@@ -59,7 +59,7 @@ static void rna_Armature_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene),
static void rna_Armature_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
DEG_relations_tag_update(bmain);
@@ -73,12 +73,12 @@ static void rna_Armature_act_bone_set(PointerRNA *ptr,
{
bArmature *arm = (bArmature *)ptr->data;
- if (value.id.data == NULL && value.data == NULL) {
+ if (value.owner_id == NULL && value.data == NULL) {
arm->act_bone = NULL;
}
else {
- if (value.id.data != arm) {
- Object *ob = (Object *)value.id.data;
+ if (value.owner_id != &arm->id) {
+ Object *ob = (Object *)value.owner_id;
if (GS(ob->id.name) != ID_OB || (ob->data != arm)) {
printf("ERROR: armature set active bone - new active doesn't come from this armature\n");
@@ -97,11 +97,11 @@ static void rna_Armature_act_edit_bone_set(PointerRNA *ptr,
{
bArmature *arm = (bArmature *)ptr->data;
- if (value.id.data == NULL && value.data == NULL) {
+ if (value.owner_id == NULL && value.data == NULL) {
arm->act_edbone = NULL;
}
else {
- if (value.id.data != arm) {
+ if (value.owner_id != &arm->id) {
/* raise an error! */
}
else {
@@ -151,7 +151,7 @@ static void rna_Armature_edit_bone_remove(bArmature *arm,
static void rna_Armature_update_layers(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bArmature *arm = ptr->id.data;
+ bArmature *arm = (bArmature *)ptr->owner_id;
Object *ob;
/* proxy lib exception, store it here so we can restore layers on file
@@ -168,7 +168,7 @@ static void rna_Armature_update_layers(Main *bmain, Scene *UNUSED(scene), Pointe
static void rna_Armature_redraw_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
DEG_id_tag_update(id, ID_RECALC_COPY_ON_WRITE);
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
@@ -177,7 +177,7 @@ static void rna_Armature_redraw_data(Main *UNUSED(bmain), Scene *UNUSED(scene),
/* called whenever a bone is renamed */
static void rna_Bone_update_renamed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
/* redraw view */
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
@@ -188,7 +188,7 @@ static void rna_Bone_update_renamed(Main *UNUSED(bmain), Scene *UNUSED(scene), P
static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
/* 1) special updates for cases where rigs try to hook into armature drawing stuff
* e.g. Mask Modifier - 'Armature' option
@@ -225,7 +225,7 @@ static void rna_Bone_select_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
static char *rna_Bone_path(PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
Bone *bone = (Bone *)ptr->data;
char name_esc[sizeof(bone->name) * 2];
@@ -295,7 +295,7 @@ static void rna_bone_layer_set(int *layer, const bool *values)
static void rna_Bone_layer_set(PointerRNA *ptr, const bool *values)
{
- bArmature *arm = (bArmature *)ptr->id.data;
+ bArmature *arm = (bArmature *)ptr->owner_id;
Bone *bone = (Bone *)ptr->data;
rna_bone_layer_set(&bone->layer, values);
@@ -331,7 +331,7 @@ static void rna_Armature_layer_set(PointerRNA *ptr, const bool *values)
static void rna_EditBone_name_set(PointerRNA *ptr, const char *value)
{
- bArmature *arm = (bArmature *)ptr->id.data;
+ bArmature *arm = (bArmature *)ptr->owner_id;
EditBone *ebone = (EditBone *)ptr->data;
char oldname[sizeof(ebone->name)], newname[sizeof(ebone->name)];
@@ -345,7 +345,7 @@ static void rna_EditBone_name_set(PointerRNA *ptr, const char *value)
static void rna_Bone_name_set(PointerRNA *ptr, const char *value)
{
- bArmature *arm = (bArmature *)ptr->id.data;
+ bArmature *arm = (bArmature *)ptr->owner_id;
Bone *bone = (Bone *)ptr->data;
char oldname[sizeof(bone->name)], newname[sizeof(bone->name)];
@@ -417,7 +417,7 @@ static void rna_EditBone_parent_set(PointerRNA *ptr,
}
else {
/* within same armature */
- if (value.id.data != ptr->id.data) {
+ if (value.owner_id != ptr->owner_id) {
return;
}
@@ -451,7 +451,7 @@ static void rna_EditBone_matrix_set(PointerRNA *ptr, const float *values)
static void rna_Bone_bbone_handle_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- bArmature *arm = (bArmature *)ptr->id.data;
+ bArmature *arm = (bArmature *)ptr->owner_id;
Bone *bone = (Bone *)ptr->data;
/* Update all users of this armature after changing B-Bone handles. */
@@ -483,7 +483,7 @@ static void rna_EditBone_bbone_prev_set(PointerRNA *ptr,
EditBone *hbone = (EditBone *)value.data;
/* Within the same armature? */
- if (hbone == NULL || value.id.data == ptr->id.data) {
+ if (hbone == NULL || value.owner_id == ptr->owner_id) {
ebone->bbone_prev = hbone;
}
}
@@ -496,7 +496,7 @@ static void rna_Bone_bbone_prev_set(PointerRNA *ptr,
Bone *hbone = (Bone *)value.data;
/* Within the same armature? */
- if (hbone == NULL || value.id.data == ptr->id.data) {
+ if (hbone == NULL || value.owner_id == ptr->owner_id) {
bone->bbone_prev = hbone;
}
}
@@ -515,7 +515,7 @@ static void rna_EditBone_bbone_next_set(PointerRNA *ptr,
EditBone *hbone = (EditBone *)value.data;
/* Within the same armature? */
- if (hbone == NULL || value.id.data == ptr->id.data) {
+ if (hbone == NULL || value.owner_id == ptr->owner_id) {
ebone->bbone_next = hbone;
}
}
@@ -528,14 +528,14 @@ static void rna_Bone_bbone_next_set(PointerRNA *ptr,
Bone *hbone = (Bone *)value.data;
/* Within the same armature? */
- if (hbone == NULL || value.id.data == ptr->id.data) {
+ if (hbone == NULL || value.owner_id == ptr->owner_id) {
bone->bbone_next = hbone;
}
}
static void rna_Armature_editbone_transform_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- bArmature *arm = (bArmature *)ptr->id.data;
+ bArmature *arm = (bArmature *)ptr->owner_id;
EditBone *ebone = (EditBone *)ptr->data;
EditBone *child;
@@ -590,7 +590,7 @@ static int rna_Armature_bones_lookup_string(PointerRNA *ptr, const char *key, Po
bArmature *arm = (bArmature *)ptr->data;
Bone *bone = BKE_armature_find_bone_name(arm, key);
if (bone) {
- RNA_pointer_create(ptr->id.data, &RNA_Bone, bone, r_ptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_Bone, bone, r_ptr);
return true;
}
else {
@@ -600,26 +600,29 @@ static int rna_Armature_bones_lookup_string(PointerRNA *ptr, const char *key, Po
static bool rna_Armature_is_editmode_get(PointerRNA *ptr)
{
- bArmature *arm = (bArmature *)ptr->id.data;
+ bArmature *arm = (bArmature *)ptr->owner_id;
return (arm->edbo != NULL);
}
-static void rna_Armature_transform(struct bArmature *arm, Main *bmain, float *mat)
+static void rna_Armature_transform(bArmature *arm, float *mat)
{
- ED_armature_transform(bmain, arm, (float(*)[4])mat, true);
+ ED_armature_transform(arm, (const float(*)[4])mat, true);
}
#else
/* Settings for curved bbone settings -
* The posemode values get applied over the top of the editmode ones. */
-void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
+void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone, bool is_editbone)
{
-# define RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone) \
+# define RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone) \
{ \
if (is_posebone) { \
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update"); \
} \
+ else if (is_editbone) { \
+ RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update"); \
+ } \
else { \
RNA_def_property_update(prop, 0, "rna_Armature_update_data"); \
} \
@@ -634,14 +637,14 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 10, 2);
RNA_def_property_ui_text(
prop, "Roll In", "Roll offset for the start of the B-Bone, adjusts twist");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
prop = RNA_def_property(srna, "bbone_rollout", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_float_sdna(prop, NULL, "roll2");
RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 10, 2);
RNA_def_property_ui_text(
prop, "Roll Out", "Roll offset for the end of the B-Bone, adjusts twist");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
if (is_posebone == false) {
prop = RNA_def_property(srna, "use_endroll_as_inroll", PROP_BOOLEAN, PROP_NONE);
@@ -658,28 +661,28 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_ui_text(
prop, "In X", "X-axis handle offset for start of the B-Bone's curve, adjusts curvature");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
prop = RNA_def_property(srna, "bbone_curveiny", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "curve_in_y");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_ui_text(
prop, "In Y", "Y-axis handle offset for start of the B-Bone's curve, adjusts curvature");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
prop = RNA_def_property(srna, "bbone_curveoutx", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "curve_out_x");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_ui_text(
prop, "Out X", "X-axis handle offset for end of the B-Bone's curve, adjusts curvature");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
prop = RNA_def_property(srna, "bbone_curveouty", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "curve_out_y");
RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_ui_text(
prop, "Out Y", "Y-axis handle offset for end of the B-Bone's curve, adjusts curvature");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
/* Ease In/Out */
prop = RNA_def_property(srna, "bbone_easein", PROP_FLOAT, PROP_NONE);
@@ -687,14 +690,14 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
RNA_def_property_ui_range(prop, -5.0f, 5.0f, 1, 3);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Ease In", "Length of first Bezier Handle (for B-Bones only)");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
prop = RNA_def_property(srna, "bbone_easeout", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "ease2");
RNA_def_property_ui_range(prop, -5.0f, 5.0f, 1, 3);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_ui_text(prop, "Ease Out", "Length of second Bezier Handle (for B-Bones only)");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
/* Scale In/Out */
prop = RNA_def_property(srna, "bbone_scaleinx", PROP_FLOAT, PROP_NONE);
@@ -706,7 +709,7 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
"Scale In X",
"X-axis scale factor for start of the B-Bone, "
"adjusts thickness (for tapering effects)");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
prop = RNA_def_property(srna, "bbone_scaleiny", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "scale_in_y");
@@ -717,7 +720,7 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
"Scale In Y",
"Y-axis scale factor for start of the B-Bone, "
"adjusts thickness (for tapering effects)");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
prop = RNA_def_property(srna, "bbone_scaleoutx", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "scale_out_x");
@@ -728,7 +731,7 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
"Scale Out X",
"X-axis scale factor for end of the B-Bone, "
"adjusts thickness (for tapering effects)");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
prop = RNA_def_property(srna, "bbone_scaleouty", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "scale_out_y");
@@ -739,7 +742,7 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone)
"Scale Out Y",
"Y-axis scale factor for end of the B-Bone, "
"adjusts thickness (for tapering effects)");
- RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone);
+ RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
# undef RNA_DEF_CURVEBONE_UPDATE
}
@@ -871,11 +874,16 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
/* Number values */
/* envelope deform settings */
prop = RNA_def_property(srna, "envelope_distance", PROP_FLOAT, PROP_DISTANCE);
+ if (editbone) {
+ RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
+ }
+ else {
+ RNA_def_property_update(prop, 0, "rna_Armature_update_data");
+ }
RNA_def_property_float_sdna(prop, NULL, "dist");
RNA_def_property_range(prop, 0.0f, 1000.0f);
RNA_def_property_ui_text(
prop, "Envelope Deform Distance", "Bone deformation distance (for Envelope deform only)");
- RNA_def_property_update(prop, 0, "rna_Armature_update_data");
prop = RNA_def_property(srna, "envelope_weight", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "weight");
@@ -914,23 +922,38 @@ static void rna_def_bone_common(StructRNA *srna, int editbone)
/* b-bones deform settings */
prop = RNA_def_property(srna, "bbone_segments", PROP_INT, PROP_NONE);
+ if (editbone) {
+ RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
+ }
+ else {
+ RNA_def_property_update(prop, 0, "rna_Armature_dependency_update");
+ }
RNA_def_property_int_sdna(prop, NULL, "segments");
RNA_def_property_range(prop, 1, 32);
RNA_def_property_ui_text(
prop, "B-Bone Segments", "Number of subdivisions of bone (for B-Bones only)");
- RNA_def_property_update(prop, 0, "rna_Armature_dependency_update");
prop = RNA_def_property(srna, "bbone_x", PROP_FLOAT, PROP_NONE);
+ if (editbone) {
+ RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
+ }
+ else {
+ RNA_def_property_update(prop, 0, "rna_Armature_update_data");
+ }
RNA_def_property_float_sdna(prop, NULL, "xwidth");
RNA_def_property_ui_range(prop, 0.0f, 1000.0f, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_ui_text(prop, "B-Bone Display X Width", "B-Bone X size");
- RNA_def_property_update(prop, 0, "rna_Armature_update_data");
prop = RNA_def_property(srna, "bbone_z", PROP_FLOAT, PROP_NONE);
+ if (editbone) {
+ RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
+ }
+ else {
+ RNA_def_property_update(prop, 0, "rna_Armature_update_data");
+ }
RNA_def_property_float_sdna(prop, NULL, "zwidth");
RNA_def_property_ui_range(prop, 0.0f, 1000.0f, 1, RNA_TRANSLATION_PREC_DEFAULT);
RNA_def_property_ui_text(prop, "B-Bone Display Z Width", "B-Bone Z size");
- RNA_def_property_update(prop, 0, "rna_Armature_update_data");
prop = RNA_def_property(srna, "bbone_handle_type_start", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "bbone_prev_type");
@@ -1010,7 +1033,7 @@ static void rna_def_bone(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Children", "Bones which are children of this bone");
rna_def_bone_common(srna, 0);
- rna_def_bone_curved_common(srna, 0);
+ rna_def_bone_curved_common(srna, false, false);
/* XXX should we define this in PoseChannel wrapping code instead?
* But PoseChannels directly get some of their flags from here... */
@@ -1133,7 +1156,7 @@ static void rna_def_edit_bone(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Armature_editbone_transform_update");
rna_def_bone_common(srna, 1);
- rna_def_bone_curved_common(srna, 0);
+ rna_def_bone_curved_common(srna, false, true);
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BONE_HIDDEN_A);
@@ -1300,7 +1323,6 @@ static void rna_def_armature(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "bArmature");
func = RNA_def_function(srna, "transform", "rna_Armature_transform");
- RNA_def_function_flag(func, FUNC_USE_MAIN);
RNA_def_function_ui_description(func, "Transform armature bones by a matrix");
parm = RNA_def_float_matrix(func, "matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Matrix", 0.0f, 0.0f);
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c
index 8f30a7e0a98..722b7b12271 100644
--- a/source/blender/makesrna/intern/rna_boid.c
+++ b/source/blender/makesrna/intern/rna_boid.c
@@ -130,10 +130,10 @@ static void rna_Boids_reset(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN
psys->recalc = ID_RECALC_PSYS_RESET;
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
}
else {
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
}
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
@@ -145,10 +145,10 @@ static void rna_Boids_reset_deps(Main *bmain, Scene *UNUSED(scene), PointerRNA *
psys->recalc = ID_RECALC_PSYS_RESET;
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
}
else {
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
}
DEG_relations_tag_update(bmain);
@@ -240,7 +240,7 @@ static void rna_BoidState_active_boid_rule_index_set(struct PointerRNA *ptr, int
static int particle_id_check(PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
return (GS(id->name) == ID_PA);
}
@@ -250,7 +250,7 @@ static char *rna_BoidSettings_path(PointerRNA *ptr)
BoidSettings *boids = (BoidSettings *)ptr->data;
if (particle_id_check(ptr)) {
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
if (part->boids == boids) {
return BLI_strdup("boids");
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 713ddfa0067..14aa9c5d8cf 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -434,27 +434,27 @@ static bool rna_BrushCapabilitiesImagePaint_has_radius_get(PointerRNA *ptr)
static PointerRNA rna_Sculpt_tool_capabilities_get(PointerRNA *ptr)
{
- return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesSculpt, ptr->id.data);
+ return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesSculpt, ptr->owner_id);
}
static PointerRNA rna_Imapaint_tool_capabilities_get(PointerRNA *ptr)
{
- return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesImagePaint, ptr->id.data);
+ return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesImagePaint, ptr->owner_id);
}
static PointerRNA rna_Vertexpaint_tool_capabilities_get(PointerRNA *ptr)
{
- return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesVertexPaint, ptr->id.data);
+ return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesVertexPaint, ptr->owner_id);
}
static PointerRNA rna_Weightpaint_tool_capabilities_get(PointerRNA *ptr)
{
- return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesWeightPaint, ptr->id.data);
+ return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilitiesWeightPaint, ptr->owner_id);
}
static PointerRNA rna_Brush_capabilities_get(PointerRNA *ptr)
{
- return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilities, ptr->id.data);
+ return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilities, ptr->owner_id);
}
static void rna_Brush_reset_icon(Brush *br)
@@ -764,7 +764,7 @@ static void rna_BrushGpencilSettings_use_material_pin_update(bContext *C, Pointe
{
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
- Brush *brush = ptr->id.data;
+ Brush *brush = (Brush *)ptr->owner_id;
if (brush->gpencil_settings->flag & GP_BRUSH_MATERIAL_PINNED) {
Material *material = give_current_material(ob, ob->actcol);
@@ -1571,6 +1571,16 @@ static void rna_def_brush(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem brush_spacing_unit_items[] = {
+ {0, "VIEW", 0, "View", "Calculate brush spacing relative to the view"},
+ {BRUSH_SCENE_SPACING,
+ "SCENE",
+ 0,
+ "Scene",
+ "Calculate brush spacing relative to the scene using the stroke location"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
static const EnumPropertyItem brush_curve_preset_items[] = {
{BRUSH_CURVE_CUSTOM, "CUSTOM", ICON_RNDCURVE, "Custom", ""},
{BRUSH_CURVE_SMOOTH, "SMOOTH", ICON_SMOOTHCURVE, "Smooth", ""},
@@ -1835,6 +1845,17 @@ static void rna_def_brush(BlenderRNA *brna)
"Best used on low-poly meshes as it has a performance impact");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "normal_radius_factor", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "normal_radius_factor");
+ RNA_def_property_float_default(prop, 0.5f);
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 3);
+ RNA_def_property_ui_text(prop,
+ "Normal Radius",
+ "Ratio between the brush radius and the radius that is going to be "
+ "used to sample the normal");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "stencil_pos", PROP_FLOAT, PROP_XYZ);
RNA_def_property_float_sdna(prop, NULL, "stencil_pos");
RNA_def_property_array(prop, 2);
@@ -1920,6 +1941,13 @@ static void rna_def_brush(BlenderRNA *brna)
"When locked keep using normal of surface where stroke was initiated");
RNA_def_property_update(prop, 0, "rna_Brush_update");
+ prop = RNA_def_property(srna, "use_scene_spacing", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
+ RNA_def_property_enum_items(prop, brush_spacing_unit_items);
+ RNA_def_property_ui_text(
+ prop, "Spacing distance", "Calculate the brush spacing using view or scene distance");
+ RNA_def_property_update(prop, 0, "rna_Brush_update");
+
prop = RNA_def_property(srna, "use_pressure_strength", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_ALPHA_PRESSURE);
RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0);
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index bb236fc3ef4..88083f600f8 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -43,52 +43,52 @@
static float rna_Camera_angle_get(PointerRNA *ptr)
{
- Camera *cam = ptr->id.data;
+ Camera *cam = (Camera *)ptr->owner_id;
float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
return focallength_to_fov(cam->lens, sensor);
}
static void rna_Camera_angle_set(PointerRNA *ptr, float value)
{
- Camera *cam = ptr->id.data;
+ Camera *cam = (Camera *)ptr->owner_id;
float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
cam->lens = fov_to_focallength(value, sensor);
}
static float rna_Camera_angle_x_get(PointerRNA *ptr)
{
- Camera *cam = ptr->id.data;
+ Camera *cam = (Camera *)ptr->owner_id;
return focallength_to_fov(cam->lens, cam->sensor_x);
}
static void rna_Camera_angle_x_set(PointerRNA *ptr, float value)
{
- Camera *cam = ptr->id.data;
+ Camera *cam = (Camera *)ptr->owner_id;
cam->lens = fov_to_focallength(value, cam->sensor_x);
}
static float rna_Camera_angle_y_get(PointerRNA *ptr)
{
- Camera *cam = ptr->id.data;
+ Camera *cam = (Camera *)ptr->owner_id;
return focallength_to_fov(cam->lens, cam->sensor_y);
}
static void rna_Camera_angle_y_set(PointerRNA *ptr, float value)
{
- Camera *cam = ptr->id.data;
+ Camera *cam = (Camera *)ptr->owner_id;
cam->lens = fov_to_focallength(value, cam->sensor_y);
}
static void rna_Camera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Camera *camera = (Camera *)ptr->id.data;
+ Camera *camera = (Camera *)ptr->owner_id;
DEG_id_tag_update(&camera->id, 0);
}
static void rna_Camera_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Camera *camera = (Camera *)ptr->id.data;
+ Camera *camera = (Camera *)ptr->owner_id;
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&camera->id, 0);
}
@@ -136,8 +136,8 @@ char *rna_CameraDOFSettings_path(PointerRNA *ptr)
* since the name used is the name of the texture assigned, but the texture
* may be used multiple times in the same stack
*/
- if (ptr->id.data) {
- if (GS(((ID *)ptr->id.data)->name) == ID_CA) {
+ if (ptr->owner_id) {
+ if (GS(ptr->owner_id->name) == ID_CA) {
return BLI_strdup("dof");
}
}
@@ -203,12 +203,14 @@ static void rna_def_camera_background_image(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "ima");
RNA_def_property_ui_text(prop, "Image", "Image displayed and edited in this space");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "clip");
RNA_def_property_ui_text(prop, "MovieClip", "Movie clip displayed and edited in this space");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "image_user", PROP_POINTER, PROP_NONE);
@@ -428,6 +430,7 @@ static void rna_def_camera_dof_settings_data(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_pointer_sdna(prop, NULL, "focus_object");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Focus Object", "Use this object to define the depth of field focal point");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dependency_update");
diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c
index 548ed656d7b..036aeebda52 100644
--- a/source/blender/makesrna/intern/rna_cloth.c
+++ b/source/blender/makesrna/intern/rna_cloth.c
@@ -45,7 +45,7 @@
static void rna_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
@@ -59,7 +59,7 @@ static void rna_cloth_dependency_update(Main *bmain, Scene *scene, PointerRNA *p
static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
/* ClothSimSettings *settings = (ClothSimSettings *)ptr->data; */
ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth);
@@ -311,7 +311,7 @@ static void rna_CollSettings_selfcol_vgroup_set(PointerRNA *ptr, const char *val
static PointerRNA rna_ClothSettings_rest_shape_key_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
return rna_object_shapekey_index_get(ob->data, sim->shapekey_rest);
@@ -321,7 +321,7 @@ static void rna_ClothSettings_rest_shape_key_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ClothSimSettings *sim = (ClothSimSettings *)ptr->data;
sim->shapekey_rest = rna_object_shapekey_index_set(ob->data, value, sim->shapekey_rest);
@@ -347,7 +347,7 @@ static void rna_ClothSettings_gravity_set(PointerRNA *ptr, const float *values)
static char *rna_ClothSettings_path(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
if (md) {
@@ -362,7 +362,7 @@ static char *rna_ClothSettings_path(PointerRNA *ptr)
static char *rna_ClothCollisionSettings_path(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth);
if (md) {
@@ -891,6 +891,7 @@ static void rna_def_cloth_collision_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "collection", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "group");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Collision Collection", "Limit colliders to this Collection");
RNA_def_property_update(prop, 0, "rna_cloth_dependency_update");
diff --git a/source/blender/makesrna/intern/rna_collection.c b/source/blender/makesrna/intern/rna_collection.c
index 12fdebbb8ca..e1c29dc906e 100644
--- a/source/blender/makesrna/intern/rna_collection.c
+++ b/source/blender/makesrna/intern/rna_collection.c
@@ -130,11 +130,11 @@ static bool rna_Collection_objects_override_apply(Main *bmain,
PointerRNA *UNUSED(ptr_item_storage),
IDOverrideLibraryPropertyOperation *opop)
{
- (void)opop;
BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE &&
"Unsupported RNA override operation on collections' objects");
+ UNUSED_VARS_NDEBUG(opop);
- Collection *coll_dst = ptr_dst->id.data;
+ Collection *coll_dst = (Collection *)ptr_dst->owner_id;
if (ptr_item_dst->type == NULL || ptr_item_src->type == NULL) {
BLI_assert(0 && "invalid source or destination object.");
@@ -233,11 +233,11 @@ static bool rna_Collection_children_override_apply(Main *bmain,
PointerRNA *UNUSED(ptr_item_storage),
IDOverrideLibraryPropertyOperation *opop)
{
- (void)opop;
BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE &&
- "Unsupported RNA override operation on collections' objects");
+ "Unsupported RNA override operation on collections' children");
+ UNUSED_VARS_NDEBUG(opop);
- Collection *coll_dst = ptr_dst->id.data;
+ Collection *coll_dst = (Collection *)ptr_dst->owner_id;
if (ptr_item_dst->type == NULL || ptr_item_src->type == NULL) {
BLI_assert(0 && "invalid source or destination sub-collection.");
@@ -482,6 +482,7 @@ void RNA_def_collections(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_ui_text(
prop, "All Objects", "Objects that are in this collection and its child collections");
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
RNA_def_property_collection_funcs(prop,
"rna_Collection_all_objects_begin",
"rna_iterator_listbase_next",
diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c
index 6bfd2b9f63b..011e373cc61 100644
--- a/source/blender/makesrna/intern/rna_color.c
+++ b/source/blender/makesrna/intern/rna_color.c
@@ -164,8 +164,8 @@ static char *rna_ColorRamp_path(PointerRNA *ptr)
char *path = NULL;
/* handle the cases where a single data-block may have 2 ramp types */
- if (ptr->id.data) {
- ID *id = ptr->id.data;
+ if (ptr->owner_id) {
+ ID *id = ptr->owner_id;
switch (GS(id->name)) {
case ID_NT: {
@@ -237,8 +237,8 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr)
/* determine the path from the ID-block to the ramp */
/* FIXME: this is a very slow way to do it, but it will have to suffice... */
- if (ptr->id.data) {
- ID *id = ptr->id.data;
+ if (ptr->owner_id) {
+ ID *id = ptr->owner_id;
switch (GS(id->name)) {
case ID_NT: {
@@ -286,12 +286,12 @@ static char *rna_ColorRampElement_path(PointerRNA *ptr)
static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- if (ptr->id.data) {
- ID *id = ptr->id.data;
+ if (ptr->owner_id) {
+ ID *id = ptr->owner_id;
switch (GS(id->name)) {
case ID_MA: {
- Material *ma = ptr->id.data;
+ Material *ma = (Material *)ptr->owner_id;
DEG_id_tag_update(&ma->id, 0);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma);
@@ -309,20 +309,20 @@ static void rna_ColorRamp_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *
break;
}
case ID_TE: {
- Tex *tex = ptr->id.data;
+ Tex *tex = (Tex *)ptr->owner_id;
DEG_id_tag_update(&tex->id, 0);
WM_main_add_notifier(NC_TEXTURE, tex);
break;
}
case ID_LS: {
- FreestyleLineStyle *linestyle = ptr->id.data;
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id;
WM_main_add_notifier(NC_LINESTYLE, linestyle);
break;
}
case ID_PA: {
- ParticleSettings *part = ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
DEG_id_tag_update(&part->id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_REDO);
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, part);
@@ -417,7 +417,7 @@ static void rna_ColorManagedDisplaySettings_display_device_update(Main *bmain,
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (!id) {
return;
@@ -582,7 +582,7 @@ static void rna_ColorManagedColorspaceSettings_reload_update(Main *bmain,
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (GS(id->name) == ID_IM) {
Image *ima = (Image *)id;
@@ -657,7 +657,7 @@ static char *rna_ColorManagedInputColorspaceSettings_path(PointerRNA *UNUSED(ptr
static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (!id) {
return;
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 6e57d16df27..05154dcc20e 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -256,6 +256,17 @@ static const EnumPropertyItem track_axis_items[] = {
{0, NULL, 0, NULL, NULL},
};
+static const EnumPropertyItem euler_order_items[] = {
+ {CONSTRAINT_EULER_AUTO, "AUTO", 0, "Default", "Euler using the default rotation order"},
+ {CONSTRAINT_EULER_XYZ, "XYZ", 0, "XYZ Euler", "Euler using the XYZ rotation order"},
+ {CONSTRAINT_EULER_XZY, "XZY", 0, "XZY Euler", "Euler using the XZY rotation order"},
+ {CONSTRAINT_EULER_YXZ, "YXZ", 0, "YXZ Euler", "Euler using the YXZ rotation order"},
+ {CONSTRAINT_EULER_YZX, "YZX", 0, "YZX Euler", "Euler using the YZX rotation order"},
+ {CONSTRAINT_EULER_ZXY, "ZXY", 0, "ZXY Euler", "Euler using the ZXY rotation order"},
+ {CONSTRAINT_EULER_ZYX, "ZYX", 0, "ZYX Euler", "Euler using the ZYX rotation order"},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
static const EnumPropertyItem space_object_items[] = {
@@ -376,8 +387,8 @@ static void rna_Constraint_name_set(PointerRNA *ptr, const char *value)
BLI_strncpy_utf8(con->name, value, sizeof(con->name));
/* make sure name is unique */
- if (ptr->id.data) {
- Object *ob = ptr->id.data;
+ if (ptr->owner_id) {
+ Object *ob = (Object *)ptr->owner_id;
ListBase *list = get_constraint_lb(ob, con, NULL);
/* if we have the list, check for unique name, otherwise give up */
@@ -418,7 +429,7 @@ static char *rna_Constraint_do_compute_path(Object *ob, bConstraint *con)
static char *rna_Constraint_path(PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bConstraint *con = ptr->data;
return rna_Constraint_do_compute_path(ob, con);
@@ -426,7 +437,7 @@ static char *rna_Constraint_path(PointerRNA *ptr)
static bConstraint *rna_constraint_from_target(PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bConstraintTarget *tgt = ptr->data;
return BKE_constraint_find_from_target(ob, tgt, NULL);
@@ -434,7 +445,7 @@ static bConstraint *rna_constraint_from_target(PointerRNA *ptr)
static char *rna_ConstraintTarget_path(PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bConstraintTarget *tgt = ptr->data;
bConstraint *con = rna_constraint_from_target(ptr);
int index = -1;
@@ -469,29 +480,30 @@ static char *rna_ConstraintTarget_path(PointerRNA *ptr)
static void rna_Constraint_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ED_object_constraint_tag_update(bmain, ptr->id.data, ptr->data);
+ ED_object_constraint_tag_update(bmain, (Object *)ptr->owner_id, ptr->data);
}
static void rna_Constraint_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ED_object_constraint_dependency_tag_update(bmain, ptr->id.data, ptr->data);
+ ED_object_constraint_dependency_tag_update(bmain, (Object *)ptr->owner_id, ptr->data);
}
static void rna_ConstraintTarget_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ED_object_constraint_tag_update(bmain, ptr->id.data, rna_constraint_from_target(ptr));
+ ED_object_constraint_tag_update(bmain, (Object *)ptr->owner_id, rna_constraint_from_target(ptr));
}
static void rna_ConstraintTarget_dependency_update(Main *bmain,
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- ED_object_constraint_dependency_tag_update(bmain, ptr->id.data, rna_constraint_from_target(ptr));
+ ED_object_constraint_dependency_tag_update(
+ bmain, (Object *)ptr->owner_id, rna_constraint_from_target(ptr));
}
static void rna_Constraint_influence_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
if (ob->pose) {
ob->pose->flag |= (POSE_LOCKED | POSE_DO_UNLOCK);
@@ -523,7 +535,7 @@ static const EnumPropertyItem *rna_Constraint_owner_space_itemf(bContext *UNUSED
PropertyRNA *UNUSED(prop),
bool *UNUSED(r_free))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bConstraint *con = (bConstraint *)ptr->data;
if (BLI_findindex(&ob->constraints, con) == -1) {
@@ -671,7 +683,7 @@ static bool rna_Constraint_cameraObject_poll(PointerRNA *ptr, PointerRNA value)
Object *ob = (Object *)value.data;
if (ob) {
- if (ob->type == OB_CAMERA && ob != (Object *)ptr->id.data) {
+ if (ob->type == OB_CAMERA && ob != (Object *)ptr->owner_id) {
return 1;
}
}
@@ -688,7 +700,7 @@ static void rna_Constraint_followTrack_camera_set(PointerRNA *ptr,
Object *ob = (Object *)value.data;
if (ob) {
- if (ob->type == OB_CAMERA && ob != (Object *)ptr->id.data) {
+ if (ob->type == OB_CAMERA && ob != (Object *)ptr->owner_id) {
data->camera = ob;
id_lib_extern((ID *)ob);
}
@@ -707,7 +719,7 @@ static void rna_Constraint_followTrack_depthObject_set(PointerRNA *ptr,
Object *ob = (Object *)value.data;
if (ob) {
- if (ob->type == OB_MESH && ob != (Object *)ptr->id.data) {
+ if (ob->type == OB_MESH && ob != (Object *)ptr->owner_id) {
data->depth_ob = ob;
id_lib_extern((ID *)ob);
}
@@ -722,7 +734,7 @@ static bool rna_Constraint_followTrack_depthObject_poll(PointerRNA *ptr, Pointer
Object *ob = (Object *)value.data;
if (ob) {
- if (ob->type == OB_MESH && ob != (Object *)ptr->id.data) {
+ if (ob->type == OB_MESH && ob != (Object *)ptr->owner_id) {
return 1;
}
}
@@ -739,7 +751,7 @@ static void rna_Constraint_objectSolver_camera_set(PointerRNA *ptr,
Object *ob = (Object *)value.data;
if (ob) {
- if (ob->type == OB_CAMERA && ob != (Object *)ptr->id.data) {
+ if (ob->type == OB_CAMERA && ob != (Object *)ptr->owner_id) {
data->camera = ob;
id_lib_extern((ID *)ob);
}
@@ -1009,7 +1021,7 @@ static void rna_def_constraint_armature_deform(BlenderRNA *brna)
RNA_def_struct_ui_text(
srna, "Armature Constraint", "Applies transformations done by the Armature modifier");
RNA_def_struct_sdna_from(srna, "bArmatureConstraint", "data");
- RNA_def_struct_ui_icon(srna, ICON_MOD_ARMATURE);
+ RNA_def_struct_ui_icon(srna, ICON_CON_ARMATURE);
prop = RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "targets", NULL);
@@ -1323,6 +1335,12 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert Z", "Invert the Z rotation");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ prop = RNA_def_property(srna, "euler_order", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "euler_order");
+ RNA_def_property_enum_items(prop, euler_order_items);
+ RNA_def_property_ui_text(prop, "Euler Order", "Explicitly specify the euler rotation order");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
prop = RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ROTLIKE_OFFSET);
RNA_def_property_ui_text(prop, "Offset", "Add original rotation into copied rotation");
@@ -1363,6 +1381,14 @@ static void rna_def_constraint_size_like(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Power", "Raise the target's scale to the specified power");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ prop = RNA_def_property(srna, "use_make_uniform", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_UNIFORM);
+ RNA_def_property_ui_text(prop,
+ "Make Uniform",
+ "Redistribute the copied change in volume equally "
+ "between the three axes of the owner");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
prop = RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_OFFSET);
RNA_def_property_ui_text(prop, "Offset", "Combine original scale with copied scale");
@@ -1876,6 +1902,18 @@ static void rna_def_constraint_transform(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Extrapolate Motion", "Extrapolate ranges");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ prop = RNA_def_property(srna, "from_rotation_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "from_rotation_mode");
+ RNA_def_property_enum_items(prop, rna_enum_driver_target_rotation_mode_items);
+ RNA_def_property_ui_text(prop, "From Mode", "Specify the type of rotation channels to use");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "to_euler_order", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "to_euler_order");
+ RNA_def_property_enum_items(prop, euler_order_items);
+ RNA_def_property_ui_text(prop, "To Order", "Explicitly specify the output euler rotation order");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
/* Loc */
prop = RNA_def_property(srna, "from_min_x", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "from_min[0]");
@@ -3026,6 +3064,7 @@ void RNA_def_constraint(BlenderRNA *brna)
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Disable", "Enable/Disable Constraint");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1);
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c
index 735cd1fd923..579dd92b703 100644
--- a/source/blender/makesrna/intern/rna_context.c
+++ b/source/blender/makesrna/intern/rna_context.c
@@ -178,14 +178,14 @@ static PointerRNA rna_Context_collection_get(PointerRNA *ptr)
static PointerRNA rna_Context_layer_collection_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
- ptr->id.data = CTX_data_scene(C);
+ ptr->owner_id = &CTX_data_scene(C)->id;
return rna_pointer_inherit_refine(ptr, &RNA_LayerCollection, CTX_data_layer_collection(C));
}
static PointerRNA rna_Context_tool_settings_get(PointerRNA *ptr)
{
bContext *C = (bContext *)ptr->data;
- ptr->id.data = CTX_data_scene(C);
+ ptr->owner_id = &CTX_data_scene(C)->id;
return rna_pointer_inherit_refine(ptr, &RNA_ToolSettings, CTX_data_tool_settings(C));
}
diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c
index 644d0b712a2..a7dac4100db 100644
--- a/source/blender/makesrna/intern/rna_curve.c
+++ b/source/blender/makesrna/intern/rna_curve.c
@@ -326,7 +326,7 @@ static void rna_Curve_texspace_size_set(PointerRNA *ptr, const float *values)
static void rna_Curve_material_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
*min = 0;
*max = max_ii(0, cu->totcol - 1);
}
@@ -347,14 +347,14 @@ static void rna_ChariInfo_material_index_set(PointerRNA *ptr, int value)
static void rna_Curve_active_textbox_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
*min = 0;
*max = max_ii(0, cu->totbox - 1);
}
static void rna_Curve_dimension_set(PointerRNA *ptr, int value)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
if (value == CU_3D) {
cu->flag |= CU_3D;
}
@@ -370,7 +370,7 @@ static const EnumPropertyItem *rna_Curve_fill_mode_itemf(bContext *UNUSED(C),
PropertyRNA *UNUSED(prop),
bool *UNUSED(r_free))
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
/* cast to quiet warning it IS a const still */
return (EnumPropertyItem *)((cu->flag & CU_3D) ? curve3d_fill_mode_items :
@@ -388,7 +388,7 @@ static int rna_Nurb_length(PointerRNA *ptr)
static void rna_Nurb_type_set(PointerRNA *ptr, int value)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
Nurb *nu = (Nurb *)ptr->data;
const int pntsu_prev = nu->pntsu;
@@ -418,7 +418,7 @@ static void rna_Curve_update_data_id(Main *UNUSED(bmain), Scene *UNUSED(scene),
static void rna_Curve_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- rna_Curve_update_data_id(bmain, scene, ptr->id.data);
+ rna_Curve_update_data_id(bmain, scene, ptr->owner_id);
}
static void rna_Curve_update_deps(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -429,7 +429,7 @@ static void rna_Curve_update_deps(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Curve_update_points(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
Nurb *nu = curve_nurb_from_point(cu, ptr->data, NULL, NULL);
if (nu) {
@@ -441,7 +441,7 @@ static void rna_Curve_update_points(Main *bmain, Scene *scene, PointerRNA *ptr)
static PointerRNA rna_Curve_bevelObject_get(PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
Object *ob = cu->bevobj;
if (ob) {
@@ -455,7 +455,7 @@ static void rna_Curve_bevelObject_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
Object *ob = (Object *)value.data;
if (ob) {
@@ -473,7 +473,7 @@ static void rna_Curve_bevelObject_set(PointerRNA *ptr,
static bool rna_Curve_otherObject_poll(PointerRNA *ptr, PointerRNA value)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
Object *ob = (Object *)value.data;
if (ob) {
@@ -487,7 +487,7 @@ static bool rna_Curve_otherObject_poll(PointerRNA *ptr, PointerRNA value)
static PointerRNA rna_Curve_taperObject_get(PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
Object *ob = cu->taperobj;
if (ob) {
@@ -501,7 +501,7 @@ static void rna_Curve_taperObject_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
Object *ob = (Object *)value.data;
if (ob) {
@@ -519,7 +519,7 @@ static void rna_Curve_taperObject_set(PointerRNA *ptr,
static void rna_Curve_resolution_u_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
ListBase *nurbs = BKE_curve_nurbs_get(cu);
Nurb *nu = nurbs->first;
@@ -533,7 +533,7 @@ static void rna_Curve_resolution_u_update_data(Main *bmain, Scene *scene, Pointe
static void rna_Curve_resolution_v_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
ListBase *nurbs = BKE_curve_nurbs_get(cu);
Nurb *nu = nurbs->first;
@@ -547,26 +547,26 @@ static void rna_Curve_resolution_v_update_data(Main *bmain, Scene *scene, Pointe
static float rna_Curve_offset_get(PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
return cu->width - 1.0f;
}
static void rna_Curve_offset_set(PointerRNA *ptr, float value)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
cu->width = 1.0f + value;
}
static int rna_Curve_body_length(PointerRNA *ptr);
static void rna_Curve_body_get(PointerRNA *ptr, char *value)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
BLI_strncpy(value, cu->str, rna_Curve_body_length(ptr) + 1);
}
static int rna_Curve_body_length(PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
return cu->len;
}
@@ -576,7 +576,7 @@ static void rna_Curve_body_set(PointerRNA *ptr, const char *value)
size_t len_bytes;
size_t len_chars = BLI_strlen_utf8_ex(value, &len_bytes);
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
cu->len_wchar = len_chars;
cu->len = len_bytes;
@@ -770,7 +770,7 @@ static void rna_Curve_active_spline_set(PointerRNA *ptr,
static char *rna_Curve_spline_path(PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
ListBase *nubase = BKE_curve_nurbs_get(cu);
Nurb *nu = ptr->data;
int index = BLI_findindex(nubase, nu);
@@ -786,7 +786,7 @@ static char *rna_Curve_spline_path(PointerRNA *ptr)
/* use for both bezier and nurbs */
static char *rna_Curve_spline_point_path(PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
Nurb *nu;
void *point = ptr->data;
int nu_index, pt_index;
@@ -808,7 +808,7 @@ static char *rna_Curve_spline_point_path(PointerRNA *ptr)
static char *rna_TextBox_path(PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
TextBox *tb = ptr->data;
int index = (int)(tb - cu->tb);
@@ -822,13 +822,13 @@ static char *rna_TextBox_path(PointerRNA *ptr)
static void rna_Curve_splines_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
rna_iterator_listbase_begin(iter, BKE_curve_nurbs_get(cu), NULL);
}
static bool rna_Curve_is_editmode_get(PointerRNA *ptr)
{
- Curve *cu = (Curve *)ptr->id.data;
+ Curve *cu = (Curve *)ptr->owner_id;
const short type = BKE_curve_type_get(cu);
if (type == OB_FONT) {
return (cu->editfont != NULL);
@@ -1229,6 +1229,7 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna)
RNA_def_property_pointer_sdna(prop, NULL, "textoncurve");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_otherObject_poll");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Text on Curve", "Curve deforming text object");
RNA_def_property_update(prop, 0, "rna_Curve_update_deps");
@@ -1236,24 +1237,28 @@ static void rna_def_font(BlenderRNA *UNUSED(brna), StructRNA *srna)
RNA_def_property_pointer_sdna(prop, NULL, "vfont");
RNA_def_property_ui_text(prop, "Font", "");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "font_bold", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "vfontb");
RNA_def_property_ui_text(prop, "Font Bold", "");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "font_italic", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "vfonti");
RNA_def_property_ui_text(prop, "Font Italic", "");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "font_bold_italic", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "vfontbi");
RNA_def_property_ui_text(prop, "Font Bold Italic", "");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Curve_update_data");
prop = RNA_def_property(srna, "edit_format", PROP_POINTER, PROP_NONE);
@@ -1646,6 +1651,7 @@ static void rna_def_curve(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_pointer_sdna(prop, NULL, "bevobj");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Bevel Object", "Curve object name that defines the bevel shape");
RNA_def_property_update(prop, 0, "rna_Curve_update_deps");
RNA_def_property_pointer_funcs(prop,
@@ -1658,6 +1664,7 @@ static void rna_def_curve(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_pointer_sdna(prop, NULL, "taperobj");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Taper Object", "Curve object name that defines the taper (width)");
RNA_def_property_update(prop, 0, "rna_Curve_update_deps");
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index 792c4450b9c..30a68a4919e 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -92,7 +92,7 @@ static void rna_DynamicPaint_redoModifier(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
}
static void rna_DynamicPaintSurfaces_updateFrames(Main *UNUSED(bmain),
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 222d2fc69da..254f3bc3710 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -132,6 +132,33 @@ const EnumPropertyItem rna_enum_beztriple_interpolation_easing_items[] = {
{0, NULL, 0, NULL, NULL},
};
+const EnumPropertyItem rna_enum_driver_target_rotation_mode_items[] = {
+ {DTAR_ROTMODE_AUTO, "AUTO", 0, "Auto Euler", "Euler using the rotation order of the target"},
+ {DTAR_ROTMODE_EULER_XYZ, "XYZ", 0, "XYZ Euler", "Euler using the XYZ rotation order"},
+ {DTAR_ROTMODE_EULER_XZY, "XZY", 0, "XZY Euler", "Euler using the XZY rotation order"},
+ {DTAR_ROTMODE_EULER_YXZ, "YXZ", 0, "YXZ Euler", "Euler using the YXZ rotation order"},
+ {DTAR_ROTMODE_EULER_YZX, "YZX", 0, "YZX Euler", "Euler using the YZX rotation order"},
+ {DTAR_ROTMODE_EULER_ZXY, "ZXY", 0, "ZXY Euler", "Euler using the ZXY rotation order"},
+ {DTAR_ROTMODE_EULER_ZYX, "ZYX", 0, "ZYX Euler", "Euler using the ZYX rotation order"},
+ {DTAR_ROTMODE_QUATERNION, "QUATERNION", 0, "Quaternion", "Quaternion rotation"},
+ {DTAR_ROTMODE_SWING_TWIST_X,
+ "SWING_TWIST_X",
+ 0,
+ "Swing and X Twist",
+ "Decompose into a swing rotation to aim the X axis, followed by twist around it"},
+ {DTAR_ROTMODE_SWING_TWIST_Y,
+ "SWING_TWIST_Y",
+ 0,
+ "Swing and Y Twist",
+ "Decompose into a swing rotation to aim the Y axis, followed by twist around it"},
+ {DTAR_ROTMODE_SWING_TWIST_Z,
+ "SWING_TWIST_Z",
+ 0,
+ "Swing and Z Twist",
+ "Decompose into a swing rotation to aim the Z axis, followed by twist around it"},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
# include "WM_api.h"
@@ -183,7 +210,7 @@ static bool rna_ChannelDriver_is_simple_expression_get(PointerRNA *ptr)
static void rna_ChannelDriver_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
ChannelDriver *driver = ptr->data;
driver->flag &= ~DRIVER_FLAG_INVALID;
@@ -211,7 +238,7 @@ static void rna_DriverTarget_update_data(Main *bmain, Scene *scene, PointerRNA *
PointerRNA driverptr;
ChannelDriver *driver;
FCurve *fcu;
- AnimData *adt = BKE_animdata_from_id(ptr->id.data);
+ AnimData *adt = BKE_animdata_from_id(ptr->owner_id);
/* find the driver this belongs to and update it */
for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
@@ -221,7 +248,7 @@ static void rna_DriverTarget_update_data(Main *bmain, Scene *scene, PointerRNA *
if (driver) {
/* FIXME: need to be able to search targets for required one... */
/*BLI_findindex(&driver->targets, ptr->data) != -1) */
- RNA_pointer_create(ptr->id.data, &RNA_Driver, driver, &driverptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_Driver, driver, &driverptr);
rna_ChannelDriver_update_data(bmain, scene, &driverptr);
return;
}
@@ -466,8 +493,8 @@ static void rna_FCurve_group_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- ID *pid = (ID *)ptr->id.data;
- ID *vid = (ID *)value.id.data;
+ ID *pid = ptr->owner_id;
+ ID *vid = value.owner_id;
FCurve *fcu = ptr->data;
bAction *act = NULL;
@@ -491,7 +518,7 @@ static void rna_FCurve_group_set(PointerRNA *ptr,
}
else {
/* the ID given is the owner of the F-Curve (for drivers) */
- AnimData *adt = BKE_animdata_from_id(ptr->id.data);
+ AnimData *adt = BKE_animdata_from_id(ptr->owner_id);
act = (adt) ? adt->action : NULL;
}
@@ -572,7 +599,7 @@ static void rna_FCurve_update_data_ex(ID *id, FCurve *fcu, Main *bmain)
static void rna_FCurve_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
BLI_assert(ptr->type == &RNA_FCurve);
- rna_FCurve_update_data_ex((ID *)ptr->id.data, (FCurve *)ptr->data, bmain);
+ rna_FCurve_update_data_ex(ptr->owner_id, (FCurve *)ptr->data, bmain);
}
static void rna_FCurve_update_data_relations(Main *bmain,
@@ -587,7 +614,7 @@ static void rna_FCurve_update_data_relations(Main *bmain,
*/
static void rna_FCurve_update_eval(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- rna_tag_animation_update(bmain, (ID *)ptr->id.data, true);
+ rna_tag_animation_update(bmain, ptr->owner_id, true);
}
static PointerRNA rna_FCurve_active_modifier_get(PointerRNA *ptr)
@@ -700,7 +727,7 @@ static void rna_FModifier_blending_range(
static void rna_FModifier_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
FModifier *fcm = (FModifier *)ptr->data;
if (fcm->curve && fcm->type == FMODIFIER_TYPE_CYCLES) {
@@ -1065,7 +1092,7 @@ static void rna_FModifierEnvelope_points_remove(
static void rna_Keyframe_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- rna_tag_animation_update(bmain, (ID *)ptr->id.data, true);
+ rna_tag_animation_update(bmain, ptr->owner_id, true);
}
#else
@@ -1671,9 +1698,12 @@ static void rna_def_drivertarget(BlenderRNA *brna)
{DTAR_TRANSCHAN_LOCX, "LOC_X", 0, "X Location", ""},
{DTAR_TRANSCHAN_LOCY, "LOC_Y", 0, "Y Location", ""},
{DTAR_TRANSCHAN_LOCZ, "LOC_Z", 0, "Z Location", ""},
+ {0, "", 0, NULL, NULL},
{DTAR_TRANSCHAN_ROTX, "ROT_X", 0, "X Rotation", ""},
{DTAR_TRANSCHAN_ROTY, "ROT_Y", 0, "Y Rotation", ""},
{DTAR_TRANSCHAN_ROTZ, "ROT_Z", 0, "Z Rotation", ""},
+ {DTAR_TRANSCHAN_ROTW, "ROT_W", 0, "W Rotation", ""},
+ {0, "", 0, NULL, NULL},
{DTAR_TRANSCHAN_SCALEX, "SCALE_X", 0, "X Scale", ""},
{DTAR_TRANSCHAN_SCALEY, "SCALE_Y", 0, "Y Scale", ""},
{DTAR_TRANSCHAN_SCALEZ, "SCALE_Z", 0, "Z Scale", ""},
@@ -1749,6 +1779,12 @@ static void rna_def_drivertarget(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Type", "Driver variable type");
RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");
+ prop = RNA_def_property(srna, "rotation_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "rotation_mode");
+ RNA_def_property_enum_items(prop, rna_enum_driver_target_rotation_mode_items);
+ RNA_def_property_ui_text(prop, "Rotation Mode", "Mode for calculating rotation channel values");
+ RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");
+
prop = RNA_def_property(srna, "transform_space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, prop_local_space_items);
diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c
index 45361702384..5d21e718934 100644
--- a/source/blender/makesrna/intern/rna_fluidsim.c
+++ b/source/blender/makesrna/intern/rna_fluidsim.c
@@ -75,7 +75,7 @@ static StructRNA *rna_FluidSettings_refine(struct PointerRNA *ptr)
static void rna_fluid_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
@@ -101,7 +101,7 @@ static int fluidsim_find_lastframe(Main *bmain, Object *ob, FluidsimSettings *fs
static void rna_fluid_find_enframe(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(
ob, eModifierType_Fluidsim);
@@ -116,7 +116,7 @@ static void rna_fluid_find_enframe(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_FluidSettings_update_type(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
FluidsimModifierData *fluidmd;
ParticleSystemModifierData *psmd;
ParticleSystem *psys, *next_psys;
@@ -177,7 +177,7 @@ static void rna_DomainFluidSettings_memory_estimate_get(PointerRNA *ptr, char *v
(void)ptr;
value[0] = '\0';
# else
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
FluidsimSettings *fss = (FluidsimSettings *)ptr->data;
fluid_estimate_memory(ob, fss, value);
diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c
index 2671246b589..01ecf2f8cae 100644
--- a/source/blender/makesrna/intern/rna_gpencil.c
+++ b/source/blender/makesrna/intern/rna_gpencil.c
@@ -144,37 +144,14 @@ static EnumPropertyItem rna_enum_gpencil_caps_modes_items[] = {
static void rna_GPencil_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_GPENCIL | NA_EDITED, NULL);
}
static void rna_GPencil_autolock(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- bGPdata *gpd = (bGPdata *)ptr->id.data;
- bGPDlayer *gpl = NULL;
-
- if (gpd->flag & GP_DATA_AUTOLOCK_LAYERS) {
- bGPDlayer *layer = BKE_gpencil_layer_getactive(gpd);
-
- /* Lock all other layers */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- /* unlock active layer */
- if (gpl == layer) {
- gpl->flag &= ~GP_LAYER_LOCKED;
- }
- else {
- gpl->flag |= GP_LAYER_LOCKED;
- }
- }
- }
- else {
- /* If disable is better unlock all layers by default or it looks there is
- * a problem in the UI because the user expects all layers will be unlocked
- */
- for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- gpl->flag &= ~GP_LAYER_LOCKED;
- }
- }
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
+ BKE_gpencil_layer_autolock_set(gpd);
/* standard update */
rna_GPencil_update(bmain, scene, ptr);
@@ -182,7 +159,7 @@ static void rna_GPencil_autolock(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_GPencil_editmode_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
/* Notify all places where GPencil data lives that the editing state is different */
@@ -194,7 +171,7 @@ static void UNUSED_FUNCTION(rna_GPencil_onion_skinning_update)(Main *bmain,
Scene *scene,
PointerRNA *ptr)
{
- bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
bGPDlayer *gpl;
bool enabled = false;
@@ -362,7 +339,7 @@ static bool rna_GPencilLayer_is_parented_get(PointerRNA *ptr)
static PointerRNA rna_GPencil_active_layer_get(PointerRNA *ptr)
{
- bGPdata *gpd = ptr->id.data;
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
if (GS(gpd->id.name) == ID_GD) { /* why would this ever be not GD */
bGPDlayer *gl;
@@ -385,7 +362,7 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- bGPdata *gpd = ptr->id.data;
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
/* Don't allow setting active layer to NULL if layers exist
* as this breaks various tools. Tools should be used instead
@@ -414,7 +391,7 @@ static void rna_GPencil_active_layer_set(PointerRNA *ptr,
static int rna_GPencil_active_layer_index_get(PointerRNA *ptr)
{
- bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
bGPDlayer *gpl = BKE_gpencil_layer_getactive(gpd);
return BLI_findindex(&gpd->layers, gpl);
@@ -422,7 +399,7 @@ static int rna_GPencil_active_layer_index_get(PointerRNA *ptr)
static void rna_GPencil_active_layer_index_set(PointerRNA *ptr, int value)
{
- bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
bGPDlayer *gpl = BLI_findlink(&gpd->layers, value);
BKE_gpencil_layer_setactive(gpd, gpl);
@@ -435,7 +412,7 @@ static void rna_GPencil_active_layer_index_set(PointerRNA *ptr, int value)
static void rna_GPencil_active_layer_index_range(
PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
{
- bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
*min = 0;
*max = max_ii(0, BLI_listbase_count(&gpd->layers) - 1);
@@ -449,7 +426,7 @@ static const EnumPropertyItem *rna_GPencil_active_layer_itemf(bContext *C,
PropertyRNA *UNUSED(prop),
bool *r_free)
{
- bGPdata *gpd = (bGPdata *)ptr->id.data;
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
bGPDlayer *gpl;
EnumPropertyItem *item = NULL, item_tmp = {0};
int totitem = 0;
@@ -478,7 +455,7 @@ static const EnumPropertyItem *rna_GPencil_active_layer_itemf(bContext *C,
static void rna_GPencilLayer_info_set(PointerRNA *ptr, const char *value)
{
- bGPdata *gpd = ptr->id.data;
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
bGPDlayer *gpl = ptr->data;
char oldname[128] = "";
@@ -539,7 +516,7 @@ static bGPDstroke *rna_GPencil_stroke_point_find_stroke(const bGPdata *gpd,
static void rna_GPencil_stroke_point_select_set(PointerRNA *ptr, const bool value)
{
- bGPdata *gpd = ptr->id.data;
+ bGPdata *gpd = (bGPdata *)ptr->owner_id;
bGPDspoint *pt = ptr->data;
bGPDstroke *gps = NULL;
@@ -1510,6 +1487,7 @@ static void rna_def_gpencil_layer(BlenderRNA *brna)
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_funcs(prop, NULL, "rna_GPencilLayer_parent_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Parent", "Parent Object");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
@@ -1648,7 +1626,7 @@ static void rna_def_gpencil_grid(BlenderRNA *brna)
prop = RNA_def_property(srna, "lines", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "lines");
- RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_range(prop, 0, SHRT_MAX);
RNA_def_property_int_default(prop, GP_DEFAULT_GRID_LINES);
RNA_def_property_ui_text(
prop, "Grid Subdivisions", "Number of subdivisions in each side of symmetry line");
@@ -1913,7 +1891,7 @@ static void rna_def_gpencil_data(BlenderRNA *brna)
prop = RNA_def_property(srna, "zdepth_offset", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "zdepth_offset");
RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.001, 5);
+ RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1f, 3);
RNA_def_property_ui_text(prop, "Surface Offset", "Offset amount when drawing in surface mode");
RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update");
diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c
index 04175d8cfd9..4a0cf4d7ce2 100644
--- a/source/blender/makesrna/intern/rna_gpencil_modifier.c
+++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c
@@ -252,8 +252,8 @@ static void rna_GpencilModifier_name_set(PointerRNA *ptr, const char *value)
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;
+ if (ptr->owner_id) {
+ Object *ob = (Object *)ptr->owner_id;
BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, gmd);
}
@@ -272,8 +272,8 @@ static char *rna_GpencilModifier_path(PointerRNA *ptr)
static void rna_GpencilModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->id.data);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->owner_id);
}
static void rna_GpencilModifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -324,7 +324,7 @@ static void greasepencil_modifier_object_set(Object *self,
PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \
{ \
_type##GpencilModifierData *tmd = (_type##GpencilModifierData *)ptr->data; \
- greasepencil_modifier_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \
+ greasepencil_modifier_object_set((Object *)ptr->owner_id, &tmd->_prop, _obtype, value); \
}
RNA_GP_MOD_OBJECT_SET(Armature, object, OB_ARMATURE);
@@ -384,6 +384,11 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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");
@@ -458,6 +463,11 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_NOISE_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -495,6 +505,11 @@ static void rna_def_modifier_gpencilsmooth(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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");
@@ -549,6 +564,11 @@ static void rna_def_modifier_gpencilsmooth(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SMOOTH_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -586,6 +606,11 @@ static void rna_def_modifier_gpencilsubdiv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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);
@@ -608,6 +633,11 @@ static void rna_def_modifier_gpencilsubdiv(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SUBDIV_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -664,6 +694,11 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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);
@@ -682,6 +717,11 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SIMPLIFY_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -721,7 +761,7 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna)
prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "distance");
RNA_def_property_range(prop, 0, 100.0f);
- RNA_def_property_ui_text(prop, "Distance", "Distance between vertex");
+ RNA_def_property_ui_text(prop, "Distance", "Distance between points");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
}
@@ -740,6 +780,11 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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");
@@ -763,6 +808,11 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_THICK_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -815,6 +865,11 @@ static void rna_def_modifier_gpenciloffset(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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");
@@ -832,6 +887,11 @@ static void rna_def_modifier_gpenciloffset(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OFFSET_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -892,6 +952,11 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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");
@@ -921,6 +986,11 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TINT_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -977,7 +1047,7 @@ static void rna_def_modifier_gpenciltime(BlenderRNA *brna)
prop = RNA_def_property(srna, "offset", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "offset");
- RNA_def_property_range(prop, -INT_MAX, INT_MAX);
+ RNA_def_property_range(prop, SHRT_MIN, SHRT_MAX);
RNA_def_property_ui_text(
prop, "Frame Offset", "Number of frames to offset original keyframe number or frame to fix");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -1039,6 +1109,11 @@ static void rna_def_modifier_gpencilcolor(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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, 1.0);
RNA_def_property_ui_range(prop, 0.0, 1.0, 0.1, 3);
@@ -1076,6 +1151,11 @@ static void rna_def_modifier_gpencilcolor(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_COLOR_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -1118,6 +1198,11 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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");
@@ -1146,6 +1231,11 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_OPACITY_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -1183,6 +1273,11 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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);
@@ -1190,7 +1285,7 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
prop = RNA_def_property(srna, "count", PROP_INT, PROP_NONE);
- RNA_def_property_range(prop, 1, INT_MAX);
+ RNA_def_property_range(prop, 1, SHRT_MAX);
RNA_def_property_ui_range(prop, 1, 50, 1, -1);
RNA_def_property_ui_text(prop, "Count", "Number of items");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
@@ -1204,6 +1299,7 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna)
"Use the location and rotation of another object to determine the distance and "
"rotational change between arrayed items");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_TRANSLATION);
@@ -1254,7 +1350,7 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna)
prop = RNA_def_property(srna, "replace_material", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "mat_rpl");
- RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_range(prop, 0, SHRT_MAX);
RNA_def_property_ui_text(
prop,
"Material",
@@ -1266,6 +1362,11 @@ static void rna_def_modifier_gpencilinstance(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_ARRAY_INVERT_PASS);
RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter");
@@ -1452,6 +1553,11 @@ static void rna_def_modifier_gpencillattice(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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");
@@ -1469,6 +1575,11 @@ static void rna_def_modifier_gpencillattice(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LATTICE_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -1495,6 +1606,7 @@ static void rna_def_modifier_gpencillattice(BlenderRNA *brna)
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_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
@@ -1520,6 +1632,11 @@ static void rna_def_modifier_gpencilmirror(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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);
@@ -1531,6 +1648,11 @@ static void rna_def_modifier_gpencilmirror(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_MIRROR_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
@@ -1551,6 +1673,7 @@ static void rna_def_modifier_gpencilmirror(BlenderRNA *brna)
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_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
prop = RNA_def_property(srna, "use_clip", PROP_BOOLEAN, PROP_NONE);
@@ -1589,6 +1712,7 @@ static void rna_def_modifier_gpencilhook(BlenderRNA *brna)
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_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_pointer_funcs(prop, NULL, "rna_HookGpencilModifier_object_set", NULL, NULL);
RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update");
@@ -1605,6 +1729,11 @@ static void rna_def_modifier_gpencilhook(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Layer", "Layer name");
RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+ prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "materialname");
+ RNA_def_property_ui_text(prop, "Material", "Material 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");
@@ -1622,6 +1751,11 @@ static void rna_def_modifier_gpencilhook(BlenderRNA *brna)
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_materials", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_HOOK_INVERT_MATERIAL);
+ RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter");
+ RNA_def_property_update(prop, 0, "rna_GpencilModifier_update");
+
prop = RNA_def_property(srna, "invert_material_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");
diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c
index 75867b2fe13..517bd2b7276 100644
--- a/source/blender/makesrna/intern/rna_image.c
+++ b/source/blender/makesrna/intern/rna_image.c
@@ -91,7 +91,7 @@ static bool rna_Image_dirty_get(PointerRNA *ptr)
static void rna_Image_source_set(PointerRNA *ptr, int value)
{
- Image *ima = ptr->id.data;
+ Image *ima = (Image *)ptr->owner_id;
if (value != ima->source) {
ima->source = value;
@@ -105,7 +105,7 @@ static void rna_Image_source_set(PointerRNA *ptr, int value)
static void rna_Image_reload_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Image *ima = ptr->id.data;
+ Image *ima = (Image *)ptr->owner_id;
BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_RELOAD);
WM_main_add_notifier(NC_IMAGE | NA_EDITED, &ima->id);
DEG_id_tag_update(&ima->id, 0);
@@ -114,13 +114,13 @@ static void rna_Image_reload_update(Main *bmain, Scene *UNUSED(scene), PointerRN
static void rna_Image_generated_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Image *ima = ptr->id.data;
+ Image *ima = (Image *)ptr->owner_id;
BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_FREE);
}
static void rna_Image_colormanage_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Image *ima = ptr->id.data;
+ Image *ima = (Image *)ptr->owner_id;
BKE_image_signal(bmain, ima, NULL, IMA_SIGNAL_COLORMANAGE);
DEG_id_tag_update(&ima->id, 0);
DEG_id_tag_update(&ima->id, ID_RECALC_EDITORS);
@@ -130,7 +130,7 @@ static void rna_Image_colormanage_update(Main *bmain, Scene *UNUSED(scene), Poin
static void rna_Image_views_format_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Image *ima = ptr->id.data;
+ Image *ima = (Image *)ptr->owner_id;
ImBuf *ibuf;
void *lock;
@@ -148,7 +148,7 @@ static void rna_Image_views_format_update(Main *bmain, Scene *scene, PointerRNA
static void rna_ImageUser_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
ImageUser *iuser = ptr->data;
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
BKE_image_user_frame_calc(NULL, iuser, scene->r.cfra);
@@ -173,10 +173,10 @@ static void rna_ImageUser_relations_update(Main *bmain, Scene *scene, PointerRNA
static char *rna_ImageUser_path(PointerRNA *ptr)
{
- if (ptr->id.data) {
+ if (ptr->owner_id) {
/* ImageUser *iuser = ptr->data; */
- switch (GS(((ID *)ptr->id.data)->name)) {
+ switch (GS(ptr->owner_id->name)) {
case ID_OB:
case ID_TE: {
return BLI_strdup("image_user");
@@ -331,7 +331,7 @@ static int rna_Image_depth_get(PointerRNA *ptr)
static int rna_Image_frame_duration_get(PointerRNA *ptr)
{
- Image *ima = ptr->id.data;
+ Image *ima = (Image *)ptr->owner_id;
int duration = 1;
if (BKE_image_has_anim(ima)) {
@@ -352,7 +352,7 @@ static int rna_Image_frame_duration_get(PointerRNA *ptr)
static int rna_Image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION])
{
- Image *ima = ptr->id.data;
+ Image *ima = (Image *)ptr->owner_id;
ImBuf *ibuf;
void *lock;
@@ -372,7 +372,7 @@ static int rna_Image_pixels_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY
static void rna_Image_pixels_get(PointerRNA *ptr, float *values)
{
- Image *ima = ptr->id.data;
+ Image *ima = (Image *)ptr->owner_id;
ImBuf *ibuf;
void *lock;
int i, size;
@@ -397,7 +397,7 @@ static void rna_Image_pixels_get(PointerRNA *ptr, float *values)
static void rna_Image_pixels_set(PointerRNA *ptr, const float *values)
{
- Image *ima = ptr->id.data;
+ Image *ima = (Image *)ptr->owner_id;
ImBuf *ibuf;
void *lock;
int i, size;
@@ -463,7 +463,7 @@ static bool rna_Image_is_float_get(PointerRNA *ptr)
static PointerRNA rna_Image_packed_file_get(PointerRNA *ptr)
{
- Image *ima = (Image *)ptr->id.data;
+ Image *ima = (Image *)ptr->owner_id;
if (BKE_image_has_packedfile(ima)) {
ImagePackedFile *imapf = ima->packedfiles.first;
@@ -485,7 +485,7 @@ static void rna_RenderSlot_clear(ID *id, RenderSlot *slot, ImageUser *iuser)
static PointerRNA rna_render_slots_active_get(PointerRNA *ptr)
{
- Image *image = (Image *)ptr->id.data;
+ Image *image = (Image *)ptr->owner_id;
RenderSlot *render_slot = BKE_image_get_renderslot(image, image->render_slot);
return rna_pointer_inherit_refine(ptr, &RNA_RenderSlot, render_slot);
@@ -495,8 +495,8 @@ static void rna_render_slots_active_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Image *image = (Image *)ptr->id.data;
- if (value.id.data == image) {
+ Image *image = (Image *)ptr->owner_id;
+ if (value.owner_id == &image->id) {
RenderSlot *slot = (RenderSlot *)value.data;
int index = BLI_findindex(&image->renderslots, slot);
if (index != -1) {
@@ -507,13 +507,13 @@ static void rna_render_slots_active_set(PointerRNA *ptr,
static int rna_render_slots_active_index_get(PointerRNA *ptr)
{
- Image *image = (Image *)ptr->id.data;
+ Image *image = (Image *)ptr->owner_id;
return image->render_slot;
}
static void rna_render_slots_active_index_set(PointerRNA *ptr, int value)
{
- Image *image = (Image *)ptr->id.data;
+ Image *image = (Image *)ptr->owner_id;
int num_slots = BLI_listbase_count(&image->renderslots);
image->render_slot = value;
CLAMP(image->render_slot, 0, num_slots - 1);
@@ -522,7 +522,7 @@ static void rna_render_slots_active_index_set(PointerRNA *ptr, int value)
static void rna_render_slots_active_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Image *image = (Image *)ptr->id.data;
+ Image *image = (Image *)ptr->owner_id;
*min = 0;
*max = max_ii(0, BLI_listbase_count(&image->renderslots) - 1);
}
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 96cdc06d901..e5058626180 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -29,15 +29,12 @@
#define RNA_MAGIC ((int)~0)
-struct Depsgraph;
struct FreestyleSettings;
struct ID;
struct IDOverrideLibrary;
-struct IDOverrideLibraryProperty;
struct IDOverrideLibraryPropertyOperation;
struct IDProperty;
struct Main;
-struct Mesh;
struct Object;
struct ReportList;
struct SDNA;
@@ -227,7 +224,7 @@ bool rna_AnimaData_override_apply(struct Main *bmain,
void rna_def_animviz_common(struct StructRNA *srna);
void rna_def_motionpath_common(struct StructRNA *srna);
-void rna_def_bone_curved_common(struct StructRNA *srna, bool is_posebone);
+void rna_def_bone_curved_common(struct StructRNA *srna, bool is_posebone, bool is_editbone);
void rna_def_texmat_common(struct StructRNA *srna, const char *texspace_editable);
void rna_def_mtex_common(struct BlenderRNA *brna,
diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h
index 60cf443383e..7c6a471b1d7 100644
--- a/source/blender/makesrna/intern/rna_internal_types.h
+++ b/source/blender/makesrna/intern/rna_internal_types.h
@@ -31,7 +31,6 @@ struct ContainerRNA;
struct FunctionRNA;
struct GHash;
struct IDOverrideLibrary;
-struct IDOverrideLibraryProperty;
struct IDOverrideLibraryPropertyOperation;
struct IDProperty;
struct Main;
diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c
index 8ab2127d898..46c3adbd6ef 100644
--- a/source/blender/makesrna/intern/rna_key.c
+++ b/source/blender/makesrna/intern/rna_key.c
@@ -87,8 +87,8 @@ static void rna_ShapeKey_name_set(PointerRNA *ptr, const char *value)
BLI_strncpy_utf8(kb->name, value, sizeof(kb->name));
/* make sure the name is truly unique */
- if (ptr->id.data) {
- Key *key = rna_ShapeKey_find_key(ptr->id.data);
+ if (ptr->owner_id) {
+ Key *key = rna_ShapeKey_find_key(ptr->owner_id);
BLI_uniquename(&key->block,
kb,
CTX_DATA_(BLT_I18NCONTEXT_ID_SHAPEKEY, "Key"),
@@ -174,7 +174,7 @@ static void rna_ShapeKey_slider_max_set(PointerRNA *ptr, float value)
static Mesh *rna_KeyBlock_normals_get_mesh(PointerRNA *ptr, ID *id)
{
- Key *key = rna_ShapeKey_find_key((id == NULL && ptr != NULL) ? ptr->id.data : id);
+ Key *key = rna_ShapeKey_find_key((id == NULL && ptr != NULL) ? ptr->owner_id : id);
id = key ? key->from : NULL;
if (id != NULL) {
@@ -315,7 +315,7 @@ static PointerRNA rna_ShapeKey_relative_key_get(PointerRNA *ptr)
{
KeyBlock *kb = (KeyBlock *)ptr->data;
- return rna_object_shapekey_index_get(ptr->id.data, kb->relative);
+ return rna_object_shapekey_index_get(ptr->owner_id, kb->relative);
}
static void rna_ShapeKey_relative_key_set(PointerRNA *ptr,
@@ -324,7 +324,7 @@ static void rna_ShapeKey_relative_key_set(PointerRNA *ptr,
{
KeyBlock *kb = (KeyBlock *)ptr->data;
- kb->relative = rna_object_shapekey_index_set(ptr->id.data, value, kb->relative);
+ kb->relative = rna_object_shapekey_index_set(ptr->owner_id, value, kb->relative);
}
static void rna_ShapeKeyPoint_co_get(PointerRNA *ptr, float *values)
@@ -565,7 +565,7 @@ static void rna_ShapeKey_data_begin_mixed(CollectionPropertyIterator *iter,
static void rna_ShapeKey_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- Key *key = rna_ShapeKey_find_key(ptr->id.data);
+ Key *key = rna_ShapeKey_find_key(ptr->owner_id);
KeyBlock *kb = (KeyBlock *)ptr->data;
int tot = kb->totelem, size = key->elemsize;
@@ -602,7 +602,7 @@ static void rna_ShapeKey_data_begin(CollectionPropertyIterator *iter, PointerRNA
static int rna_ShapeKey_data_length(PointerRNA *ptr)
{
- Key *key = rna_ShapeKey_find_key(ptr->id.data);
+ Key *key = rna_ShapeKey_find_key(ptr->owner_id);
KeyBlock *kb = (KeyBlock *)ptr->data;
int tot = kb->totelem;
@@ -615,7 +615,7 @@ static int rna_ShapeKey_data_length(PointerRNA *ptr)
static PointerRNA rna_ShapeKey_data_get(CollectionPropertyIterator *iter)
{
- Key *key = rna_ShapeKey_find_key(iter->parent.id.data);
+ Key *key = rna_ShapeKey_find_key(iter->parent.owner_id);
void *ptr = rna_iterator_array_get(iter);
StructRNA *type = &RNA_ShapeKeyPoint;
@@ -637,7 +637,7 @@ static PointerRNA rna_ShapeKey_data_get(CollectionPropertyIterator *iter)
int rna_ShapeKey_data_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr)
{
- Key *key = rna_ShapeKey_find_key(ptr->id.data);
+ Key *key = rna_ShapeKey_find_key(ptr->owner_id);
KeyBlock *kb = (KeyBlock *)ptr->data;
int elemsize = key->elemsize;
char *databuf = kb->data;
@@ -672,7 +672,7 @@ int rna_ShapeKey_data_lookup_int(PointerRNA *ptr, int index, PointerRNA *r_ptr)
static char *rna_ShapeKey_path(PointerRNA *ptr)
{
KeyBlock *kb = (KeyBlock *)ptr->data;
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
char name_esc[sizeof(kb->name) * 2];
BLI_strescape(name_esc, kb->name, sizeof(name_esc));
@@ -687,7 +687,7 @@ static char *rna_ShapeKey_path(PointerRNA *ptr)
static void rna_Key_update_data(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Key *key = ptr->id.data;
+ Key *key = (Key *)ptr->owner_id;
Object *ob;
for (ob = bmain->objects.first; ob; ob = ob->id.next) {
@@ -756,8 +756,8 @@ static int rna_ShapeKeyPoint_get_index(Key *key, KeyBlock *kb, float *point)
static char *rna_ShapeKeyPoint_path(PointerRNA *ptr)
{
- ID *id = (ID *)ptr->id.data;
- Key *key = rna_ShapeKey_find_key(ptr->id.data);
+ ID *id = ptr->owner_id;
+ Key *key = rna_ShapeKey_find_key(ptr->owner_id);
KeyBlock *kb;
float *point = (float *)ptr->data;
@@ -1034,6 +1034,7 @@ static void rna_def_key(BlenderRNA *brna)
prop = RNA_def_property(srna, "user", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
RNA_def_property_pointer_sdna(prop, NULL, "from");
RNA_def_property_ui_text(prop, "User", "Data-block using these shape keys");
diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c
index 5a8223af28a..34f5b6caee1 100644
--- a/source/blender/makesrna/intern/rna_lattice.c
+++ b/source/blender/makesrna/intern/rna_lattice.c
@@ -49,7 +49,7 @@
static void rna_LatticePoint_co_get(PointerRNA *ptr, float *values)
{
- Lattice *lt = (Lattice *)ptr->id.data;
+ Lattice *lt = (Lattice *)ptr->owner_id;
BPoint *bp = (BPoint *)ptr->data;
int index = bp - lt->def;
int u, v, w;
@@ -63,7 +63,7 @@ static void rna_LatticePoint_co_get(PointerRNA *ptr, float *values)
static void rna_LatticePoint_groups_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- Lattice *lt = (Lattice *)ptr->id.data;
+ Lattice *lt = (Lattice *)ptr->owner_id;
if (lt->dvert) {
BPoint *bp = (BPoint *)ptr->data;
@@ -95,7 +95,7 @@ static void rna_Lattice_points_begin(CollectionPropertyIterator *iter, PointerRN
static void rna_Lattice_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
DEG_id_tag_update(id, 0);
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
@@ -109,8 +109,8 @@ static void rna_Lattice_update_data_editlatt(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- ID *id = ptr->id.data;
- Lattice *lt = (Lattice *)ptr->id.data;
+ ID *id = ptr->owner_id;
+ Lattice *lt = (Lattice *)ptr->owner_id;
if (lt->editlatt) {
Lattice *lt_em = lt->editlatt->latt;
@@ -127,7 +127,7 @@ static void rna_Lattice_update_data_editlatt(Main *UNUSED(bmain),
static void rna_Lattice_update_size(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Lattice *lt = ptr->id.data;
+ Lattice *lt = (Lattice *)ptr->owner_id;
Object *ob;
int newu, newv, neww;
@@ -224,7 +224,7 @@ static void rna_Lattice_vg_name_set(PointerRNA *ptr, const char *value)
/* annoying, but is a consequence of RNA structures... */
static char *rna_LatticePoint_path(PointerRNA *ptr)
{
- Lattice *lt = (Lattice *)ptr->id.data;
+ Lattice *lt = (Lattice *)ptr->owner_id;
void *point = ptr->data;
BPoint *points = NULL;
@@ -251,7 +251,7 @@ static char *rna_LatticePoint_path(PointerRNA *ptr)
static bool rna_Lattice_is_editmode_get(PointerRNA *ptr)
{
- Lattice *lt = (Lattice *)ptr->id.data;
+ Lattice *lt = (Lattice *)ptr->owner_id;
return (lt->editlatt != NULL);
}
diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c
index c9b51707759..1ad006cbc37 100644
--- a/source/blender/makesrna/intern/rna_layer.c
+++ b/source/blender/makesrna/intern/rna_layer.c
@@ -152,7 +152,7 @@ static int rna_ViewLayer_objects_selected_skip(CollectionPropertyIterator *iter,
static PointerRNA rna_ViewLayer_depsgraph_get(PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (GS(id->name) == ID_SCE) {
Scene *scene = (Scene *)id;
ViewLayer *view_layer = (ViewLayer *)ptr->data;
@@ -274,7 +274,7 @@ static void rna_LayerCollection_exclude_update_recursive(ListBase *lb, const boo
static void rna_LayerCollection_exclude_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
LayerCollection *lc = (LayerCollection *)ptr->data;
ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc);
@@ -294,7 +294,7 @@ static void rna_LayerCollection_exclude_update(Main *bmain, Scene *UNUSED(scene)
static void rna_LayerCollection_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
LayerCollection *lc = (LayerCollection *)ptr->data;
ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc);
diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c
index 79ba5970007..8640c35f1b8 100644
--- a/source/blender/makesrna/intern/rna_light.c
+++ b/source/blender/makesrna/intern/rna_light.c
@@ -77,7 +77,7 @@ static StructRNA *rna_Light_refine(struct PointerRNA *ptr)
static void rna_Light_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Light *la = ptr->id.data;
+ Light *la = (Light *)ptr->owner_id;
DEG_id_tag_update(&la->id, 0);
WM_main_add_notifier(NC_LAMP | ND_LIGHTING, la);
@@ -85,7 +85,7 @@ static void rna_Light_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
static void rna_Light_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Light *la = ptr->id.data;
+ Light *la = (Light *)ptr->owner_id;
DEG_id_tag_update(&la->id, 0);
WM_main_add_notifier(NC_LAMP | ND_LIGHTING_DRAW, la);
diff --git a/source/blender/makesrna/intern/rna_lightprobe.c b/source/blender/makesrna/intern/rna_lightprobe.c
index b6d6fac587e..463cefdf3f0 100644
--- a/source/blender/makesrna/intern/rna_lightprobe.c
+++ b/source/blender/makesrna/intern/rna_lightprobe.c
@@ -43,7 +43,7 @@
static void rna_LightProbe_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
}
#else
@@ -212,6 +212,7 @@ static void rna_def_lightprobe(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_pointer_sdna(prop, NULL, "visibility_grp");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Visibility Collection", "Restrict objects visible for this probe");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING, "rna_LightProbe_recalc");
diff --git a/source/blender/makesrna/intern/rna_linestyle.c b/source/blender/makesrna/intern/rna_linestyle.c
index 936a5e6a53d..f6cfc33c82e 100644
--- a/source/blender/makesrna/intern/rna_linestyle.c
+++ b/source/blender/makesrna/intern/rna_linestyle.c
@@ -287,7 +287,7 @@ static char *rna_LineStyle_geometry_modifier_path(PointerRNA *ptr)
static void rna_LineStyleColorModifier_name_set(PointerRNA *ptr, const char *value)
{
- FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id;
LineStyleModifier *m = (LineStyleModifier *)ptr->data;
BLI_strncpy_utf8(m->name, value, sizeof(m->name));
@@ -301,7 +301,7 @@ static void rna_LineStyleColorModifier_name_set(PointerRNA *ptr, const char *val
static void rna_LineStyleAlphaModifier_name_set(PointerRNA *ptr, const char *value)
{
- FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id;
LineStyleModifier *m = (LineStyleModifier *)ptr->data;
BLI_strncpy_utf8(m->name, value, sizeof(m->name));
@@ -315,7 +315,7 @@ static void rna_LineStyleAlphaModifier_name_set(PointerRNA *ptr, const char *val
static void rna_LineStyleThicknessModifier_name_set(PointerRNA *ptr, const char *value)
{
- FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id;
LineStyleModifier *m = (LineStyleModifier *)ptr->data;
BLI_strncpy_utf8(m->name, value, sizeof(m->name));
@@ -329,7 +329,7 @@ static void rna_LineStyleThicknessModifier_name_set(PointerRNA *ptr, const char
static void rna_LineStyleGeometryModifier_name_set(PointerRNA *ptr, const char *value)
{
- FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id;
LineStyleModifier *m = (LineStyleModifier *)ptr->data;
BLI_strncpy_utf8(m->name, value, sizeof(m->name));
@@ -343,13 +343,13 @@ static void rna_LineStyleGeometryModifier_name_set(PointerRNA *ptr, const char *
static void rna_LineStyle_mtex_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id;
rna_iterator_array_begin(iter, (void *)linestyle->mtex, sizeof(MTex *), MAX_MTEX, 0, NULL);
}
static PointerRNA rna_LineStyle_active_texture_get(PointerRNA *ptr)
{
- FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id;
Tex *tex;
tex = give_current_linestyle_texture(linestyle);
@@ -360,14 +360,14 @@ static void rna_LineStyle_active_texture_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->id.data;
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id;
set_current_linestyle_texture(linestyle, value.data);
}
static void rna_LineStyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- FreestyleLineStyle *linestyle = ptr->id.data;
+ FreestyleLineStyle *linestyle = (FreestyleLineStyle *)ptr->owner_id;
DEG_id_tag_update(&linestyle->id, 0);
WM_main_add_notifier(NC_LINESTYLE, linestyle);
diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c
index abbbd04143c..adc041174aa 100644
--- a/source/blender/makesrna/intern/rna_mask.c
+++ b/source/blender/makesrna/intern/rna_mask.c
@@ -58,7 +58,7 @@
static void rna_Mask_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Mask *mask = ptr->id.data;
+ Mask *mask = (Mask *)ptr->owner_id;
WM_main_add_notifier(NC_MASK | ND_DATA, mask);
DEG_id_tag_update(&mask->id, 0);
@@ -147,21 +147,21 @@ static void rna_MaskParent_id_type_set(PointerRNA *ptr, int value)
static void rna_Mask_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- Mask *mask = (Mask *)ptr->id.data;
+ Mask *mask = (Mask *)ptr->owner_id;
rna_iterator_listbase_begin(iter, &mask->masklayers, NULL);
}
static int rna_Mask_layer_active_index_get(PointerRNA *ptr)
{
- Mask *mask = (Mask *)ptr->id.data;
+ Mask *mask = (Mask *)ptr->owner_id;
return mask->masklay_act;
}
static void rna_Mask_layer_active_index_set(PointerRNA *ptr, int value)
{
- Mask *mask = (Mask *)ptr->id.data;
+ Mask *mask = (Mask *)ptr->owner_id;
mask->masklay_act = value;
}
@@ -169,7 +169,7 @@ static void rna_Mask_layer_active_index_set(PointerRNA *ptr, int value)
static void rna_Mask_layer_active_index_range(
PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax)
{
- Mask *mask = (Mask *)ptr->id.data;
+ Mask *mask = (Mask *)ptr->owner_id;
*min = 0;
*max = max_ii(0, mask->masklay_tot - 1);
@@ -188,7 +188,7 @@ static char *rna_MaskLayer_path(PointerRNA *ptr)
static PointerRNA rna_Mask_layer_active_get(PointerRNA *ptr)
{
- Mask *mask = (Mask *)ptr->id.data;
+ Mask *mask = (Mask *)ptr->owner_id;
MaskLayer *masklay = BKE_mask_layer_active(mask);
return rna_pointer_inherit_refine(ptr, &RNA_MaskLayer, masklay);
@@ -198,7 +198,7 @@ static void rna_Mask_layer_active_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Mask *mask = (Mask *)ptr->id.data;
+ Mask *mask = (Mask *)ptr->owner_id;
MaskLayer *masklay = (MaskLayer *)value.data;
BKE_mask_layer_active_set(mask, masklay);
@@ -213,7 +213,7 @@ static void rna_MaskLayer_splines_begin(CollectionPropertyIterator *iter, Pointe
static void rna_MaskLayer_name_set(PointerRNA *ptr, const char *value)
{
- Mask *mask = (Mask *)ptr->id.data;
+ Mask *mask = (Mask *)ptr->owner_id;
MaskLayer *masklay = (MaskLayer *)ptr->data;
char oldname[sizeof(masklay->name)], newname[sizeof(masklay->name)];
@@ -351,7 +351,7 @@ static void rna_MaskSplinePoint_handle_type_set(PointerRNA *ptr, int value)
{
MaskSplinePoint *point = (MaskSplinePoint *)ptr->data;
BezTriple *bezt = &point->bezt;
- MaskSpline *spline = mask_spline_from_point((Mask *)ptr->id.data, point);
+ MaskSpline *spline = mask_spline_from_point((Mask *)ptr->owner_id, point);
bezt->h1 = bezt->h2 = value;
mask_point_check_stick(point);
@@ -370,7 +370,7 @@ static void rna_MaskSplinePoint_handle_left_type_set(PointerRNA *ptr, int value)
{
MaskSplinePoint *point = (MaskSplinePoint *)ptr->data;
BezTriple *bezt = &point->bezt;
- MaskSpline *spline = mask_spline_from_point((Mask *)ptr->id.data, point);
+ MaskSpline *spline = mask_spline_from_point((Mask *)ptr->owner_id, point);
bezt->h1 = value;
mask_point_check_stick(point);
@@ -389,7 +389,7 @@ static void rna_MaskSplinePoint_handle_right_type_set(PointerRNA *ptr, int value
{
MaskSplinePoint *point = (MaskSplinePoint *)ptr->data;
BezTriple *bezt = &point->bezt;
- MaskSpline *spline = mask_spline_from_point((Mask *)ptr->id.data, point);
+ MaskSpline *spline = mask_spline_from_point((Mask *)ptr->owner_id, point);
bezt->h2 = value;
mask_point_check_stick(point);
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index 3a7e58fbaa4..885df13724f 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -39,7 +39,7 @@ const EnumPropertyItem rna_enum_ramp_blend_items[] = {
{0, "", ICON_NONE, NULL, NULL},
{MA_RAMP_DARK, "DARKEN", 0, "Darken", ""},
{MA_RAMP_MULT, "MULTIPLY", 0, "Multiply", ""},
- {MA_RAMP_BURN, "BURN", 0, "Burn", ""},
+ {MA_RAMP_BURN, "BURN", 0, "Color Burn", ""},
{0, "", ICON_NONE, NULL, NULL},
{MA_RAMP_LIGHT, "LIGHTEN", 0, "Lighten", ""},
{MA_RAMP_SCREEN, "SCREEN", 0, "Screen", ""},
@@ -91,7 +91,7 @@ const EnumPropertyItem rna_enum_ramp_blend_items[] = {
static void rna_Material_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Material *ma = ptr->id.data;
+ Material *ma = (Material *)ptr->owner_id;
DEG_id_tag_update(&ma->id, ID_RECALC_SHADING);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING, ma);
@@ -101,7 +101,7 @@ static void rna_Material_update_previews(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- Material *ma = ptr->id.data;
+ Material *ma = (Material *)ptr->owner_id;
if (ma->nodetree) {
BKE_node_preview_clear_tree(ma->nodetree);
@@ -112,7 +112,7 @@ static void rna_Material_update_previews(Main *UNUSED(bmain),
static void rna_MaterialGpencil_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Material *ma = ptr->id.data;
+ Material *ma = (Material *)ptr->owner_id;
rna_Material_update(bmain, scene, ptr);
WM_main_add_notifier(NC_GPENCIL | ND_DATA, ma);
@@ -120,7 +120,7 @@ static void rna_MaterialGpencil_update(Main *bmain, Scene *scene, PointerRNA *pt
static void rna_MaterialGpencil_nopreview_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Material *ma = ptr->id.data;
+ Material *ma = (Material *)ptr->owner_id;
rna_Material_update(bmain, scene, ptr);
WM_main_add_notifier(NC_GPENCIL | ND_DATA, ma);
@@ -128,7 +128,7 @@ static void rna_MaterialGpencil_nopreview_update(Main *bmain, Scene *scene, Poin
static void rna_Material_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Material *ma = ptr->id.data;
+ Material *ma = (Material *)ptr->owner_id;
DEG_id_tag_update(&ma->id, ID_RECALC_SHADING);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma);
@@ -146,7 +146,7 @@ static void rna_Material_active_paint_texture_index_update(Main *bmain,
PointerRNA *ptr)
{
bScreen *sc;
- Material *ma = ptr->id.data;
+ Material *ma = (Material *)ptr->owner_id;
if (ma->use_nodes && ma->nodetree) {
struct bNode *node = BKE_texpaint_slot_material_find_node(ma, ma->paint_active_slot);
@@ -305,7 +305,7 @@ static bool rna_is_grease_pencil_get(PointerRNA *ptr)
static void rna_gpcolordata_uv_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
/* update all uv strokes of this color */
- Material *ma = ptr->id.data;
+ Material *ma = (Material *)ptr->owner_id;
ED_gpencil_update_color_uv(bmain, ma);
rna_MaterialGpencil_update(bmain, scene, ptr);
@@ -421,12 +421,14 @@ static void rna_def_material_display(StructRNA *srna)
prop = RNA_def_property(srna, "diffuse_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "r");
RNA_def_property_array(prop, 4);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Diffuse Color", "Diffuse color of the material");
RNA_def_property_update(prop, 0, "rna_Material_draw_update");
prop = RNA_def_property(srna, "specular_color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_float_sdna(prop, NULL, "specr");
RNA_def_property_array(prop, 3);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Specular Color", "Specular color of the material");
RNA_def_property_update(prop, 0, "rna_Material_draw_update");
@@ -434,6 +436,7 @@ static void rna_def_material_display(StructRNA *srna)
RNA_def_property_float_sdna(prop, NULL, "roughness");
RNA_def_property_float_default(prop, 0.25f);
RNA_def_property_range(prop, 0, 1);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Roughness", "Roughness of the material");
RNA_def_property_update(prop, 0, "rna_Material_draw_update");
@@ -441,12 +444,14 @@ static void rna_def_material_display(StructRNA *srna)
RNA_def_property_float_sdna(prop, NULL, "spec");
RNA_def_property_float_default(prop, 0.5f);
RNA_def_property_range(prop, 0, 1);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Specular", "How intense (bright) the specular reflection is");
RNA_def_property_update(prop, 0, "rna_Material_draw_update");
prop = RNA_def_property(srna, "metallic", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "metallic");
RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Metallic", "Amount of mirror reflection for raytrace");
RNA_def_property_update(prop, 0, "rna_Material_update");
@@ -778,6 +783,7 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
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_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Image", "");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
@@ -800,6 +806,7 @@ static void rna_def_material_greasepencil(BlenderRNA *brna)
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_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Image", "");
RNA_def_property_update(prop, NC_GPENCIL | ND_SHADING, "rna_MaterialGpencil_update");
diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c
index 99428fd872b..704bb11fc8a 100644
--- a/source/blender/makesrna/intern/rna_mesh.c
+++ b/source/blender/makesrna/intern/rna_mesh.c
@@ -80,7 +80,7 @@ const EnumPropertyItem rna_enum_mesh_delimit_mode_items[] = {
static Mesh *rna_mesh(PointerRNA *ptr)
{
- Mesh *me = (Mesh *)ptr->id.data;
+ Mesh *me = (Mesh *)ptr->owner_id;
return me;
}
@@ -146,7 +146,7 @@ static void rna_cd_layer_name_set(CustomData *cdata, CustomDataLayer *cdl, const
static CustomData *rna_cd_from_layer(PointerRNA *ptr, CustomDataLayer *cdl)
{
/* find out where we come from by */
- Mesh *me = ptr->id.data;
+ Mesh *me = (Mesh *)ptr->owner_id;
CustomData *cd;
/* rely on negative values wrapping */
@@ -202,7 +202,7 @@ static bool rna_Mesh_has_custom_normals_get(PointerRNA *ptr)
static void rna_Mesh_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
/* cheating way for importers to avoid slow updates */
if (id->us > 0) {
@@ -226,7 +226,7 @@ static void rna_Mesh_update_data_edit_active_color(Main *bmain, Scene *scene, Po
}
static void rna_Mesh_update_select(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
/* cheating way for importers to avoid slow updates */
if (id->us > 0) {
WM_main_add_notifier(NC_GEOM | ND_SELECT, id);
@@ -235,7 +235,7 @@ static void rna_Mesh_update_select(Main *UNUSED(bmain), Scene *UNUSED(scene), Po
void rna_Mesh_update_draw(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
/* cheating way for importers to avoid slow updates */
if (id->us > 0) {
WM_main_add_notifier(NC_GEOM | ND_DATA, id);
@@ -403,7 +403,7 @@ static void rna_MeshPolygon_center_get(PointerRNA *ptr, float *values)
static float rna_MeshPolygon_area_get(PointerRNA *ptr)
{
- Mesh *me = (Mesh *)ptr->id.data;
+ Mesh *me = (Mesh *)ptr->owner_id;
MPoly *mp = (MPoly *)ptr->data;
return BKE_mesh_calc_poly_area(mp, me->mloop + mp->loopstart, me->mvert);
@@ -571,7 +571,7 @@ static int rna_CustomDataLayer_clone_get(PointerRNA *ptr, CustomData *data, int
static void rna_CustomDataLayer_active_set(
PointerRNA *ptr, CustomData *data, int value, int type, int render)
{
- Mesh *me = ptr->id.data;
+ Mesh *me = (Mesh *)ptr->owner_id;
int n = (((CustomDataLayer *)ptr->data) - data->layers) - CustomData_get_layer_index(data, type);
if (value == 0) {
@@ -651,14 +651,6 @@ static void rna_MPoly_freestyle_face_mark_set(PointerRNA *ptr, int value)
}
}
-/* Generic UV rename! */
-static void rna_MeshUVLayer_name_set(PointerRNA *ptr, const char *name)
-{
- char buf[MAX_CUSTOMDATA_LAYER_NAME];
- BLI_strncpy_utf8(buf, name, MAX_CUSTOMDATA_LAYER_NAME);
- BKE_mesh_uv_cdlayer_rename(rna_mesh(ptr), ((CustomDataLayer *)ptr->data)->name, buf, true);
-}
-
/* uv_layers */
DEFINE_CUSTOMDATA_LAYER_COLLECTION(uv_layer, ldata, CD_MLOOPUV)
@@ -1378,7 +1370,7 @@ static int rna_MeshPolygonStringPropertyLayer_data_length(PointerRNA *ptr)
}
/* XXX, we dont have proper byte string support yet, so for now use the (bytes + 1)
- * bmesh API exposes correct python/bytestring access */
+ * bmesh API exposes correct python/byte-string access. */
void rna_MeshStringProperty_s_get(PointerRNA *ptr, char *value)
{
MStringProperty *ms = (MStringProperty *)ptr->data;
@@ -1941,7 +1933,7 @@ static void rna_def_mloopuv(BlenderRNA *brna)
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_struct_name_property(srna, prop);
- RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshUVLayer_name_set");
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_MeshLoopLayer_name_set");
RNA_def_property_ui_text(prop, "Name", "Name of UV map");
RNA_def_property_update(prop, 0, "rna_Mesh_update_data");
@@ -2789,6 +2781,7 @@ static void rna_def_mesh(BlenderRNA *brna)
prop = RNA_def_property(srna, "texture_mesh", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "texcomesh");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop,
"Texture Mesh",
@@ -3053,6 +3046,7 @@ static void rna_def_mesh(BlenderRNA *brna)
prop = RNA_def_property(srna, "texco_mesh", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "texcomesh");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Texture Space Mesh", "Derive texture coordinates from another mesh");
diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c
index 283590fc529..0b3a7802082 100644
--- a/source/blender/makesrna/intern/rna_mesh_api.c
+++ b/source/blender/makesrna/intern/rna_mesh_api.c
@@ -311,11 +311,6 @@ void RNA_api_mesh(StructRNA *srna)
0,
"Calculate Loose Edges",
"Calculate the loose state of each edge");
- RNA_def_boolean(func,
- "calc_loop_triangles",
- 0,
- "Calculate Triangules",
- "Force recalculation of triangle tessellation");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
RNA_def_function(srna, "update_gpu_tag", "rna_Mesh_update_gpu_tag");
diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c
index 743bac2b709..451bdda45f5 100644
--- a/source/blender/makesrna/intern/rna_meta.c
+++ b/source/blender/makesrna/intern/rna_meta.c
@@ -89,7 +89,7 @@ static void rna_Meta_texspace_size_set(PointerRNA *ptr, const float *values)
static void rna_MetaBall_update_data(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- MetaBall *mb = ptr->id.data;
+ MetaBall *mb = (MetaBall *)ptr->owner_id;
Object *ob;
/* cheating way for importers to avoid slow updates */
@@ -158,13 +158,13 @@ static void rna_MetaBall_elements_clear(MetaBall *mb)
static bool rna_Meta_is_editmode_get(PointerRNA *ptr)
{
- MetaBall *mb = ptr->id.data;
+ MetaBall *mb = (MetaBall *)ptr->owner_id;
return (mb->editelems != NULL);
}
static char *rna_MetaElement_path(PointerRNA *ptr)
{
- MetaBall *mb = ptr->id.data;
+ MetaBall *mb = (MetaBall *)ptr->owner_id;
MetaElem *ml = ptr->data;
int index = -1;
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index cae9e2a8c9b..18cf57c5624 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -609,8 +609,8 @@ static void rna_Modifier_name_set(PointerRNA *ptr, const char *value)
BLI_strncpy_utf8(md->name, value, sizeof(md->name));
/* make sure the name is truly unique */
- if (ptr->id.data) {
- Object *ob = ptr->id.data;
+ if (ptr->owner_id) {
+ Object *ob = (Object *)ptr->owner_id;
modifier_unique_name(&ob->modifiers, md);
}
@@ -629,8 +629,8 @@ static char *rna_Modifier_path(PointerRNA *ptr)
static void rna_Modifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->id.data);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->owner_id);
}
static void rna_Modifier_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -737,7 +737,7 @@ static void modifier_object_set(Object *self, Object **ob_p, int type, PointerRN
PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \
{ \
_type##ModifierData *tmd = (_type##ModifierData *)ptr->data; \
- modifier_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \
+ modifier_object_set((Object *)ptr->owner_id, &tmd->_prop, _obtype, value); \
}
RNA_MOD_OBJECT_SET(Armature, object, OB_ARMATURE);
@@ -760,7 +760,7 @@ static void rna_HookModifier_object_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Object *owner = (Object *)ptr->id.data;
+ Object *owner = (Object *)ptr->owner_id;
HookModifierData *hmd = ptr->data;
Object *ob = (Object *)value.data;
@@ -769,9 +769,50 @@ static void rna_HookModifier_object_set(PointerRNA *ptr,
BKE_object_modifier_hook_reset(owner, hmd);
}
+static bool rna_HookModifier_object_override_apply(Main *UNUSED(bmain),
+ PointerRNA *ptr_dst,
+ PointerRNA *ptr_src,
+ PointerRNA *ptr_storage,
+ PropertyRNA *prop_dst,
+ PropertyRNA *prop_src,
+ PropertyRNA *UNUSED(prop_storage),
+ const int len_dst,
+ const int len_src,
+ const int len_storage,
+ PointerRNA *UNUSED(ptr_item_dst),
+ PointerRNA *UNUSED(ptr_item_src),
+ PointerRNA *UNUSED(ptr_item_storage),
+ IDOverrideLibraryPropertyOperation *opop)
+{
+ BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage) && len_dst == 0);
+ BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE &&
+ "Unsupported RNA override operation on Hook modifier target objet pointer");
+ UNUSED_VARS_NDEBUG(ptr_storage, len_dst, len_src, len_storage, opop);
+
+ /* We need a special handling here because setting hook target resets invert parent matrix,
+ * which is evil in our case. */
+ HookModifierData *hmd = ptr_dst->data;
+ Object *owner = (Object *)ptr_dst->owner_id;
+ Object *target_dst = RNA_property_pointer_get(ptr_dst, prop_dst).data;
+ Object *target_src = RNA_property_pointer_get(ptr_src, prop_src).data;
+
+ BLI_assert(target_dst == hmd->object);
+
+ if (target_src == target_dst) {
+ return false;
+ }
+
+ hmd->object = target_src;
+ if (target_src == NULL) {
+ /* The only case where we do want default behavior (with matrix reset). */
+ BKE_object_modifier_hook_reset(owner, hmd);
+ }
+ return true;
+}
+
static void rna_HookModifier_subtarget_set(PointerRNA *ptr, const char *value)
{
- Object *owner = (Object *)ptr->id.data;
+ Object *owner = (Object *)ptr->owner_id;
HookModifierData *hmd = ptr->data;
BLI_strncpy(hmd->subtarget, value, sizeof(hmd->subtarget));
@@ -858,7 +899,7 @@ static void rna_UVProjector_object_set(PointerRNA *ptr,
static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr)
{
SmokeModifierData *smd = (SmokeModifierData *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
/* nothing changed */
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) {
@@ -885,7 +926,7 @@ static void rna_Smoke_set_type(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_MultiresModifier_type_set(PointerRNA *ptr, int value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
MultiresModifierData *mmd = (MultiresModifierData *)ptr->data;
multires_force_update(ob);
@@ -903,7 +944,7 @@ static void rna_MultiresModifier_level_range(
static bool rna_MultiresModifier_external_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Mesh *me = ob->data;
return CustomData_external_test(&me->ldata, CD_MDISPS);
@@ -911,7 +952,7 @@ static bool rna_MultiresModifier_external_get(PointerRNA *ptr)
static void rna_MultiresModifier_filepath_get(PointerRNA *ptr, char *value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
CustomDataExternal *external = ((Mesh *)ob->data)->ldata.external;
BLI_strncpy(value, (external) ? external->filename : "", sizeof(external->filename));
@@ -919,7 +960,7 @@ static void rna_MultiresModifier_filepath_get(PointerRNA *ptr, char *value)
static void rna_MultiresModifier_filepath_set(PointerRNA *ptr, const char *value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
CustomDataExternal *external = ((Mesh *)ob->data)->ldata.external;
if (external && !STREQ(external->filename, value)) {
@@ -930,7 +971,7 @@ static void rna_MultiresModifier_filepath_set(PointerRNA *ptr, const char *value
static int rna_MultiresModifier_filepath_length(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
CustomDataExternal *external = ((Mesh *)ob->data)->ldata.external;
return strlen((external) ? external->filename : "");
@@ -955,19 +996,19 @@ static bool rna_MeshDeformModifier_is_bound_get(PointerRNA *ptr)
static PointerRNA rna_SoftBodyModifier_settings_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return rna_pointer_inherit_refine(ptr, &RNA_SoftBodySettings, ob->soft);
}
static PointerRNA rna_SoftBodyModifier_point_cache_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return rna_pointer_inherit_refine(ptr, &RNA_PointCache, ob->soft->shared->pointcache);
}
static PointerRNA rna_CollisionModifier_settings_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return rna_pointer_inherit_refine(ptr, &RNA_CollisionSettings, ob->pd);
}
@@ -1574,6 +1615,7 @@ static void rna_def_modifier_generic_map_info(StructRNA *srna)
prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Texture", "");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "texture_coords", PROP_ENUM, PROP_NONE);
@@ -1593,6 +1635,7 @@ static void rna_def_modifier_generic_map_info(StructRNA *srna)
RNA_def_property_ui_text(
prop, "Texture Coordinate Object", "Object to set the texture coordinates");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
}
@@ -1609,11 +1652,13 @@ static void rna_def_modifier_warp(BlenderRNA *brna)
prop = RNA_def_property(srna, "object_from", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "From", "Object to transform from");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "object_to", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "To", "Object to transform to");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_NONE);
@@ -1729,6 +1774,7 @@ static void rna_def_modifier_lattice(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_LatticeModifier_object_set", NULL, "rna_Lattice_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -1772,6 +1818,7 @@ static void rna_def_modifier_curve(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_CurveModifier_object_set", NULL, "rna_Curve_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_CurveModifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -1930,6 +1977,7 @@ static void rna_def_modifier_mirror(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "mirror_ob");
RNA_def_property_ui_text(prop, "Mirror Object", "Object to use as mirror");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
}
@@ -2028,7 +2076,7 @@ static void rna_def_modifier_decimate(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_dissolve_boundaries", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS);
RNA_def_property_ui_text(
- prop, "All Boundaries", "Dissolve all vertices inbetween face boundaries (planar only)");
+ prop, "All Boundaries", "Dissolve all vertices in between face boundaries (planar only)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "delimit", PROP_ENUM, PROP_NONE);
@@ -2139,6 +2187,7 @@ static void rna_def_modifier_wave(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "objectcenter");
RNA_def_property_ui_text(prop, "Start Position Object", "Object which defines the wave center");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -2294,6 +2343,8 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
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_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
+ RNA_def_property_override_funcs(prop, NULL, NULL, "rna_HookModifier_object_override_apply");
RNA_def_property_pointer_funcs(prop, NULL, "rna_HookModifier_object_set", NULL, NULL);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
@@ -2394,6 +2445,7 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_BooleanModifier_object_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE);
@@ -2482,6 +2534,7 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ArrayModifier_curve_ob_set", NULL, "rna_Curve_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_ArrayModifier_dependency_update");
/* Offset parameters */
@@ -2545,6 +2598,7 @@ static void rna_def_modifier_array(BlenderRNA *brna)
"Use the location and rotation of another object to determine the distance and "
"rotational change between arrayed items");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
/* Caps */
@@ -2553,6 +2607,7 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ArrayModifier_start_cap_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
prop = RNA_def_property(srna, "end_cap", PROP_POINTER, PROP_NONE);
@@ -2560,6 +2615,7 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ArrayModifier_end_cap_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "offset_u", PROP_FLOAT, PROP_FACTOR);
@@ -2772,6 +2828,7 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, "rna_UVProjector_object_get", "rna_UVProjector_object_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Object", "Object to use as projector transform");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
}
@@ -3016,6 +3073,7 @@ static void rna_def_modifier_cast(BlenderRNA *brna)
"Control object: if available, its location determines the center of the effect");
RNA_def_property_pointer_funcs(prop, NULL, "rna_CastModifier_object_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
@@ -3098,6 +3156,7 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_MeshDeformModifier_object_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "is_bound", PROP_BOOLEAN, PROP_NONE);
@@ -3183,6 +3242,7 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
RNA_def_property_ui_text(prop, "Object", "Object that has the particle system");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "particle_system_index", PROP_INT, PROP_NONE);
@@ -3750,6 +3810,7 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ShrinkwrapModifier_target_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "auxiliary_target", PROP_POINTER, PROP_NONE);
@@ -3758,6 +3819,7 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_ShrinkwrapModifier_auxTarget_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -3875,6 +3937,7 @@ static void rna_def_modifier_mask(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_MaskModifier_ob_arm_set", NULL, "rna_Armature_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
@@ -3953,6 +4016,7 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
prop = RNA_def_property(srna, "origin", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Origin", "Offset the origin and orientation of the deformation");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_NONE);
@@ -4146,6 +4210,7 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "ob_axis");
RNA_def_property_ui_text(prop, "Object", "Object to define the screw axis");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "steps", PROP_INT, PROP_UNSIGNED);
@@ -4272,6 +4337,7 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "object_src");
RNA_def_property_ui_text(prop, "Object From", "Object defining offset");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "bone_from", PROP_STRING, PROP_NONE);
@@ -4283,6 +4349,7 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "object_dst");
RNA_def_property_ui_text(prop, "Object To", "Object defining offset");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "bone_to", PROP_STRING, PROP_NONE);
@@ -4350,6 +4417,7 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
prop = RNA_def_property(srna, "mask_texture", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Masking Tex", "Masking texture");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "mask_tex_use_channel", PROP_ENUM, PROP_NONE);
@@ -4378,6 +4446,7 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
"Which object to take texture "
"coordinates from");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
}
@@ -4647,6 +4716,7 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "proximity_ob_target");
RNA_def_property_ui_text(prop, "Target Object", "Object to calculate vertices distances from");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "min_dist", PROP_FLOAT, PROP_DISTANCE);
@@ -5210,6 +5280,7 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "CacheFile");
RNA_def_property_ui_text(prop, "Cache File", "");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "object_path", PROP_STRING, PROP_NONE);
@@ -5411,6 +5482,7 @@ static void rna_def_modifier_datatransfer(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "ob_source");
RNA_def_property_ui_text(prop, "Source Object", "Object to transfer data from");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_pointer_funcs(
prop, NULL, "rna_DataTransferModifier_ob_source_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
@@ -5816,6 +5888,7 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Target", "Target object used to affect normals");
RNA_def_property_pointer_funcs(prop, NULL, "rna_NormalEditModifier_target_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "use_direction_parallel", PROP_BOOLEAN, PROP_NONE);
@@ -5843,6 +5916,7 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_SurfaceDeformModifier_target_set", NULL, "rna_Mesh_object_poll");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
prop = RNA_def_property(srna, "falloff", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c
index 10e19b92dda..9bfa93ceba5 100644
--- a/source/blender/makesrna/intern/rna_movieclip.c
+++ b/source/blender/makesrna/intern/rna_movieclip.c
@@ -53,14 +53,14 @@
static void rna_MovieClip_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
DEG_id_tag_update(&clip->id, ID_RECALC_SOURCE);
}
static void rna_MovieClip_size_get(PointerRNA *ptr, int *values)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
values[0] = clip->lastsize[0];
values[1] = clip->lastsize[1];
@@ -68,13 +68,13 @@ static void rna_MovieClip_size_get(PointerRNA *ptr, int *values)
static float rna_MovieClip_fps_get(PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
return BKE_movieclip_get_fps(clip);
}
static void rna_MovieClip_use_proxy_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
BKE_movieclip_clear_cache(clip);
BKE_sequence_invalidate_movieclip_strips(bmain, clip);
}
@@ -83,7 +83,7 @@ static void rna_MovieClipUser_proxy_render_settings_update(Main *bmain,
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- ID *id = (ID *)ptr->id.data;
+ ID *id = ptr->owner_id;
MovieClipUser *user = (MovieClipUser *)ptr->data;
/* when changing render settings of space clip user
diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c
index 6f55fb4e24c..97cab783aed 100644
--- a/source/blender/makesrna/intern/rna_nla.c
+++ b/source/blender/makesrna/intern/rna_nla.c
@@ -65,8 +65,8 @@ static void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value)
BLI_strncpy_utf8(data->name, value, sizeof(data->name));
/* validate if there's enough info to do so */
- if (ptr->id.data) {
- AnimData *adt = BKE_animdata_from_id(ptr->id.data);
+ if (ptr->owner_id) {
+ AnimData *adt = BKE_animdata_from_id(ptr->owner_id);
BKE_nlastrip_validate_name(adt, data);
}
}
@@ -74,7 +74,7 @@ static void rna_NlaStrip_name_set(PointerRNA *ptr, const char *value)
static char *rna_NlaStrip_path(PointerRNA *ptr)
{
NlaStrip *strip = (NlaStrip *)ptr->data;
- AnimData *adt = BKE_animdata_from_id(ptr->id.data);
+ AnimData *adt = BKE_animdata_from_id(ptr->owner_id);
/* if we're attached to AnimData, try to resolve path back to AnimData */
if (adt) {
@@ -103,7 +103,7 @@ static char *rna_NlaStrip_path(PointerRNA *ptr)
static void rna_NlaStrip_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
ANIM_id_update(bmain, id);
}
@@ -122,9 +122,9 @@ static void rna_NlaStrip_transform_update(Main *bmain, Scene *scene, PointerRNA
BKE_nlameta_flush_transforms(strip);
/* set the flag */
- if ((strip->flag & NLASTRIP_FLAG_AUTO_BLENDS) && ptr->id.data) {
+ if ((strip->flag & NLASTRIP_FLAG_AUTO_BLENDS) && ptr->owner_id) {
/* validate state to ensure that auto-blend gets applied immediately */
- IdAdtTemplate *iat = (IdAdtTemplate *)ptr->id.data;
+ IdAdtTemplate *iat = (IdAdtTemplate *)ptr->owner_id;
if (iat->adt) {
BKE_nla_validate_state(iat->adt);
@@ -274,8 +274,8 @@ static void rna_NlaStrip_use_auto_blend_set(PointerRNA *ptr, bool value)
data->flag |= NLASTRIP_FLAG_AUTO_BLENDS;
/* validate state to ensure that auto-blend gets applied immediately */
- if (ptr->id.data) {
- IdAdtTemplate *iat = (IdAdtTemplate *)ptr->id.data;
+ if (ptr->owner_id) {
+ IdAdtTemplate *iat = (IdAdtTemplate *)ptr->owner_id;
if (iat->adt) {
BKE_nla_validate_state(iat->adt);
@@ -298,8 +298,8 @@ static int rna_NlaStrip_action_editable(PointerRNA *ptr, const char **UNUSED(r_i
NlaStrip *strip = (NlaStrip *)ptr->data;
/* strip actions shouldn't be editable if NLA tweakmode is on */
- if (ptr->id.data) {
- AnimData *adt = BKE_animdata_from_id(ptr->id.data);
+ if (ptr->owner_id) {
+ AnimData *adt = BKE_animdata_from_id(ptr->owner_id);
if (adt) {
/* active action is only editable when it is not a tweaking strip */
@@ -475,7 +475,7 @@ static void rna_NlaStrip_remove(
static void rna_NlaTrack_solo_set(PointerRNA *ptr, bool value)
{
NlaTrack *data = (NlaTrack *)ptr->data;
- AnimData *adt = BKE_animdata_from_id(ptr->id.data);
+ AnimData *adt = BKE_animdata_from_id(ptr->owner_id);
NlaTrack *nt;
if (data == NULL) {
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index c9815a6cc37..0909aa42a4d 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -63,10 +63,13 @@ const EnumPropertyItem rna_enum_node_socket_in_out_items[] = {
{SOCK_IN, "IN", 0, "Input", ""}, {SOCK_OUT, "OUT", 0, "Output", ""}, {0, NULL, 0, NULL, NULL}};
#ifndef RNA_RUNTIME
-static const EnumPropertyItem rna_enum_node_socket_draw_shape_items[] = {
- {SOCK_DRAW_SHAPE_CIRCLE, "CIRCLE", 0, "Circle", ""},
- {SOCK_DRAW_SHAPE_SQUARE, "SQUARE", 0, "Square", ""},
- {SOCK_DRAW_SHAPE_DIAMOND, "DIAMOND", 0, "Diamond", ""},
+static const EnumPropertyItem rna_enum_node_socket_display_shape_items[] = {
+ {SOCK_DISPLAY_SHAPE_CIRCLE, "CIRCLE", 0, "Circle", ""},
+ {SOCK_DISPLAY_SHAPE_SQUARE, "SQUARE", 0, "Square", ""},
+ {SOCK_DISPLAY_SHAPE_DIAMOND, "DIAMOND", 0, "Diamond", ""},
+ {SOCK_DISPLAY_SHAPE_CIRCLE_DOT, "CIRCLE_DOT", 0, "Circle with inner dot", ""},
+ {SOCK_DISPLAY_SHAPE_SQUARE_DOT, "SQUARE_DOT", 0, "Square with inner dot", ""},
+ {SOCK_DISPLAY_SHAPE_DIAMOND_DOT, "DIAMOND_DOT", 0, "Diamond with inner dot", ""},
{0, NULL, 0, NULL, NULL}};
static const EnumPropertyItem node_socket_type_items[] = {
@@ -100,44 +103,81 @@ static const EnumPropertyItem node_chunksize_items[] = {
#endif
const EnumPropertyItem rna_enum_node_math_items[] = {
- {NODE_MATH_ADD, "ADD", 0, "Add", ""},
- {NODE_MATH_SUB, "SUBTRACT", 0, "Subtract", ""},
- {NODE_MATH_MUL, "MULTIPLY", 0, "Multiply", ""},
- {NODE_MATH_DIVIDE, "DIVIDE", 0, "Divide", ""},
+ {NODE_MATH_ADD, "ADD", 0, "Add", "A + B"},
+ {NODE_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", "A - B"},
+ {NODE_MATH_MULTIPLY, "MULTIPLY", 0, "Multiply", "A * B"},
+ {NODE_MATH_DIVIDE, "DIVIDE", 0, "Divide", "A / B"},
{0, "", ICON_NONE, NULL, NULL},
- {NODE_MATH_POW, "POWER", 0, "Power", ""},
- {NODE_MATH_LOG, "LOGARITHM", 0, "Logarithm", ""},
- {NODE_MATH_SQRT, "SQRT", 0, "Square Root", ""},
- {NODE_MATH_ABS, "ABSOLUTE", 0, "Absolute", ""},
+ {NODE_MATH_POWER, "POWER", 0, "Power", "A power B"},
+ {NODE_MATH_LOGARITHM, "LOGARITHM", 0, "Logarithm", "Logarithm A base B"},
+ {NODE_MATH_SQRT, "SQRT", 0, "Square Root", "Square root of A"},
+ {NODE_MATH_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Magnitude of A"},
{0, "", ICON_NONE, NULL, NULL},
- {NODE_MATH_MIN, "MINIMUM", 0, "Minimum", ""},
- {NODE_MATH_MAX, "MAXIMUM", 0, "Maximum", ""},
- {NODE_MATH_LESS, "LESS_THAN", 0, "Less Than", ""},
- {NODE_MATH_GREATER, "GREATER_THAN", 0, "Greater Than", ""},
+ {NODE_MATH_MINIMUM, "MINIMUM", 0, "Minimum", "The minimum from A and B"},
+ {NODE_MATH_MAXIMUM, "MAXIMUM", 0, "Maximum", "The maximum from A and B"},
+ {NODE_MATH_LESS_THAN, "LESS_THAN", 0, "Less Than", "1 if A < B else 0"},
+ {NODE_MATH_GREATER_THAN, "GREATER_THAN", 0, "Greater Than", "1 if A > B else 0"},
{0, "", ICON_NONE, NULL, NULL},
- {NODE_MATH_ROUND, "ROUND", 0, "Round", ""},
- {NODE_MATH_FLOOR, "FLOOR", 0, "Floor", ""},
- {NODE_MATH_CEIL, "CEIL", 0, "Ceil", ""},
- {NODE_MATH_FRACT, "FRACT", 0, "Fract", ""},
- {NODE_MATH_MOD, "MODULO", 0, "Modulo", ""},
+ {NODE_MATH_ROUND,
+ "ROUND",
+ 0,
+ "Round",
+ "Round A to the nearest integer. Round upward if the fraction part is 0.5"},
+ {NODE_MATH_FLOOR, "FLOOR", 0, "Floor", "The largest integer smaller than or equal A"},
+ {NODE_MATH_CEIL, "CEIL", 0, "Ceil", "The smallest integer greater than or equal A"},
+ {NODE_MATH_FRACTION, "FRACT", 0, "Fraction", "The fraction part of A"},
+ {NODE_MATH_MODULO, "MODULO", 0, "Modulo", "A mod B"},
{0, "", ICON_NONE, NULL, NULL},
- {NODE_MATH_SIN, "SINE", 0, "Sine", ""},
- {NODE_MATH_COS, "COSINE", 0, "Cosine", ""},
- {NODE_MATH_TAN, "TANGENT", 0, "Tangent", ""},
- {NODE_MATH_ASIN, "ARCSINE", 0, "Arcsine", ""},
- {NODE_MATH_ACOS, "ARCCOSINE", 0, "Arccosine", ""},
- {NODE_MATH_ATAN, "ARCTANGENT", 0, "Arctangent", ""},
- {NODE_MATH_ATAN2, "ARCTAN2", 0, "Arctan2", ""},
+ {NODE_MATH_SINE, "SINE", 0, "Sine", "sin(A)"},
+ {NODE_MATH_COSINE, "COSINE", 0, "Cosine", "cos(A)"},
+ {NODE_MATH_TANGENT, "TANGENT", 0, "Tangent", "tan(A)"},
+ {NODE_MATH_ARCSINE, "ARCSINE", 0, "Arcsine", "arcsin(A)"},
+ {NODE_MATH_ARCCOSINE, "ARCCOSINE", 0, "Arccosine", "arccos(A)"},
+ {NODE_MATH_ARCTANGENT, "ARCTANGENT", 0, "Arctangent", "arctan(A)"},
+ {NODE_MATH_ARCTAN2, "ARCTAN2", 0, "Arctan2", "The signed angle arctan(A / B)"},
{0, NULL, 0, NULL, NULL},
};
const EnumPropertyItem rna_enum_node_vec_math_items[] = {
- {0, "ADD", 0, "Add", ""},
- {1, "SUBTRACT", 0, "Subtract", ""},
- {2, "AVERAGE", 0, "Average", ""},
- {3, "DOT_PRODUCT", 0, "Dot Product", ""},
- {4, "CROSS_PRODUCT", 0, "Cross Product", ""},
- {5, "NORMALIZE", 0, "Normalize", ""},
+ {NODE_VECTOR_MATH_ADD, "ADD", 0, "Add", "A + B"},
+ {NODE_VECTOR_MATH_SUBTRACT, "SUBTRACT", 0, "Subtract", "A - B"},
+ {NODE_VECTOR_MATH_MULTIPLY, "MULTIPLY", 0, "Multiply", "Entrywise multiply"},
+ {NODE_VECTOR_MATH_DIVIDE, "DIVIDE", 0, "Divide", "Entrywise divide"},
+ {0, "", ICON_NONE, NULL, NULL},
+ {NODE_VECTOR_MATH_CROSS_PRODUCT, "CROSS_PRODUCT", 0, "Cross Product", "A cross B"},
+ {NODE_VECTOR_MATH_PROJECT, "PROJECT", 0, "Project", "Project A onto B"},
+ {NODE_VECTOR_MATH_REFLECT,
+ "REFLECT",
+ 0,
+ "Reflect",
+ "Reflect A around the normal B. B needn't be normalized"},
+ {NODE_VECTOR_MATH_DOT_PRODUCT, "DOT_PRODUCT", 0, "Dot Product", "A dot B"},
+ {0, "", ICON_NONE, NULL, NULL},
+ {NODE_VECTOR_MATH_DISTANCE, "DISTANCE", 0, "Distance", "Distance between A and B"},
+ {NODE_VECTOR_MATH_LENGTH, "LENGTH", 0, "Length", "Length of A"},
+ {NODE_VECTOR_MATH_SCALE, "SCALE", 0, "Scale", "A multiplied by Scale"},
+ {NODE_VECTOR_MATH_NORMALIZE, "NORMALIZE", 0, "Normalize", "Normalize A"},
+ {0, "", ICON_NONE, NULL, NULL},
+ {NODE_VECTOR_MATH_SNAP,
+ "SNAP",
+ 0,
+ "Snap",
+ "Round A to the largest integer multiple of B less than or equal A"},
+ {NODE_VECTOR_MATH_FLOOR, "FLOOR", 0, "Floor", "Entrywise floor"},
+ {NODE_VECTOR_MATH_CEIL, "CEIL", 0, "Ceil", "Entrywise ceil"},
+ {NODE_VECTOR_MATH_MODULO, "MODULO", 0, "Modulo", "Entrywise modulo"},
+ {NODE_VECTOR_MATH_FRACTION, "FRACTION", 0, "Fraction", "The fraction part of A entrywise"},
+ {NODE_VECTOR_MATH_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Entrywise absolute"},
+ {NODE_VECTOR_MATH_MINIMUM, "MINIMUM", 0, "Minimum", "Entrywise minimum"},
+ {NODE_VECTOR_MATH_MAXIMUM, "MAXIMUM", 0, "Maximum", "Entrywise maximum"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static const EnumPropertyItem rna_enum_node_tex_dimensions_items[] = {
+ {1, "1D", 0, "1D", "Use the scalar value W as input"},
+ {2, "2D", 0, "2D", "Use the 2D vector (x, y) as input. The z component is ignored"},
+ {3, "3D", 0, "3D", "Use the 3D vector Vector as input"},
+ {4, "4D", 0, "4D", "Use the 4D vector (x, y, z, w) as input"},
{0, NULL, 0, NULL, NULL},
};
@@ -720,7 +760,7 @@ static bool rna_NodeTree_check(bNodeTree *ntree, ReportList *reports)
static void rna_NodeTree_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
WM_main_add_notifier(NC_NODE | NA_EDITED, NULL);
@@ -1201,7 +1241,7 @@ static char *rna_Node_path(PointerRNA *ptr)
char *rna_Node_ImageUser_path(PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node;
char name_esc[sizeof(node->name) * 2];
@@ -1706,7 +1746,7 @@ static bool rna_Node_parent_poll(PointerRNA *ptr, PointerRNA value)
static void rna_Node_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
ED_node_tag_update_nodetree(bmain, ntree, node);
}
@@ -1730,7 +1770,7 @@ static void rna_Node_select_set(PointerRNA *ptr, bool value)
static void rna_Node_name_set(PointerRNA *ptr, const char *value)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
char oldname[sizeof(node->name)];
@@ -2082,7 +2122,7 @@ static StructRNA *rna_NodeSocket_refine(PointerRNA *ptr)
static char *rna_NodeSocket_path(PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = (bNodeSocket *)ptr->data;
bNode *node;
int socketindex;
@@ -2116,7 +2156,7 @@ static IDProperty *rna_NodeSocket_idprops(PointerRNA *ptr, bool create)
static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = (bNodeSocket *)ptr->data;
bNode *node;
PointerRNA r_ptr;
@@ -2129,7 +2169,7 @@ static PointerRNA rna_NodeSocket_node_get(PointerRNA *ptr)
static void rna_NodeSocket_type_set(PointerRNA *ptr, int value)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = (bNodeSocket *)ptr->data;
bNode *node;
nodeFindNode(ntree, sock, &node, NULL);
@@ -2138,7 +2178,7 @@ static void rna_NodeSocket_type_set(PointerRNA *ptr, int value)
static void rna_NodeSocket_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = (bNodeSocket *)ptr->data;
bNode *node;
if (nodeFindNode(ntree, sock, &node, NULL)) {
@@ -2398,7 +2438,7 @@ static StructRNA *rna_NodeSocketInterface_refine(PointerRNA *ptr)
static char *rna_NodeSocketInterface_path(PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = (bNodeSocket *)ptr->data;
int socketindex;
@@ -2429,7 +2469,7 @@ static IDProperty *rna_NodeSocketInterface_idprops(PointerRNA *ptr, bool create)
static void rna_NodeSocketInterface_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *stemp = ptr->data;
if (!stemp->typeinfo) {
@@ -2545,7 +2585,7 @@ static void rna_NodeSocketStandard_value_update(struct bContext *C, PointerRNA *
/* try to use node from context, faster */
node = CTX_data_pointer_get(C, "node").data;
if (!node) {
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeSocket *sock = ptr->data;
/* fall back to searching node in the tree */
@@ -2763,7 +2803,7 @@ static void rna_CompositorNode_tag_need_exec(bNode *node)
static void rna_Node_tex_image_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
ED_node_tag_update_nodetree(bmain, ntree, node);
@@ -2772,7 +2812,7 @@ static void rna_Node_tex_image_update(Main *bmain, Scene *UNUSED(scene), Pointer
static void rna_NodeGroup_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
if (node->id) {
@@ -2786,7 +2826,7 @@ static void rna_NodeGroup_node_tree_set(PointerRNA *ptr,
const PointerRNA value,
struct ReportList *UNUSED(reports))
{
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = ptr->data;
bNodeTree *ngroup = value.data;
@@ -2804,7 +2844,7 @@ static void rna_NodeGroup_node_tree_set(PointerRNA *ptr,
static bool rna_NodeGroup_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
{
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeTree *ngroup = value.data;
/* only allow node trees of the same type as the group node's tree */
@@ -2831,7 +2871,7 @@ static StructRNA *rna_NodeGroup_interface_typef(PointerRNA *ptr)
static StructRNA *rna_NodeGroupInputOutput_interface_typef(PointerRNA *ptr)
{
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
if (ntree) {
StructRNA *srna = ntreeInterfaceTypeGet(ntree, true);
@@ -3166,7 +3206,7 @@ static const EnumPropertyItem *rna_Node_channel_itemf(bContext *UNUSED(C),
static void rna_Image_Node_update_id(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
node->update |= NODE_UPDATE_ID;
@@ -3190,19 +3230,19 @@ static PointerRNA rna_NodeOutputFile_slot_file_get(CollectionPropertyIterator *i
{
PointerRNA ptr;
bNodeSocket *sock = rna_iterator_listbase_get(iter);
- RNA_pointer_create(iter->parent.id.data, &RNA_NodeOutputFileSlotFile, sock->storage, &ptr);
+ RNA_pointer_create(iter->parent.owner_id, &RNA_NodeOutputFileSlotFile, sock->storage, &ptr);
return ptr;
}
static void rna_NodeColorBalance_update_lgg(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- ntreeCompositColorBalanceSyncFromLGG(ptr->id.data, ptr->data);
+ ntreeCompositColorBalanceSyncFromLGG((bNodeTree *)ptr->owner_id, ptr->data);
rna_Node_update(bmain, scene, ptr);
}
static void rna_NodeColorBalance_update_cdl(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- ntreeCompositColorBalanceSyncFromCDL(ptr->id.data, ptr->data);
+ ntreeCompositColorBalanceSyncFromCDL((bNodeTree *)ptr->owner_id, ptr->data);
rna_Node_update(bmain, scene, ptr);
}
@@ -3241,13 +3281,13 @@ static void rna_NodeCryptomatte_matte_set(PointerRNA *ptr, const char *value)
static void rna_NodeCryptomatte_update_add(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- ntreeCompositCryptomatteSyncFromAdd(ptr->id.data, ptr->data);
+ ntreeCompositCryptomatteSyncFromAdd((bNodeTree *)ptr->owner_id, 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);
+ ntreeCompositCryptomatteSyncFromRemove((bNodeTree *)ptr->owner_id, ptr->data);
rna_Node_update(bmain, scene, ptr);
}
@@ -3257,7 +3297,7 @@ static PointerRNA rna_NodeOutputFile_slot_layer_get(CollectionPropertyIterator *
{
PointerRNA ptr;
bNodeSocket *sock = rna_iterator_listbase_get(iter);
- RNA_pointer_create(iter->parent.id.data, &RNA_NodeOutputFileSlotLayer, sock->storage, &ptr);
+ RNA_pointer_create(iter->parent.owner_id, &RNA_NodeOutputFileSlotLayer, sock->storage, &ptr);
return ptr;
}
@@ -3287,7 +3327,7 @@ static int rna_NodeOutputFileSocket_find_node(bNodeTree *ntree,
static void rna_NodeOutputFileSlotFile_path_set(PointerRNA *ptr, const char *value)
{
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
NodeImageMultiFileSocket *sockdata = ptr->data;
bNode *node;
bNodeSocket *sock;
@@ -3299,7 +3339,7 @@ static void rna_NodeOutputFileSlotFile_path_set(PointerRNA *ptr, const char *val
static void rna_NodeOutputFileSlotLayer_name_set(PointerRNA *ptr, const char *value)
{
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
NodeImageMultiFileSocket *sockdata = ptr->data;
bNode *node;
bNodeSocket *sock;
@@ -3420,7 +3460,7 @@ static void rna_ShaderNodeScript_bytecode_set(PointerRNA *ptr, const char *value
static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
RenderEngineType *engine_type = RE_engines_find(scene->r.engine);
@@ -3436,7 +3476,7 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p
static void rna_ShaderNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
nodeUpdate(ntree, node);
@@ -3445,7 +3485,7 @@ static void rna_ShaderNode_socket_update(Main *bmain, Scene *scene, PointerRNA *
static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- bNodeTree *ntree = (bNodeTree *)ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
nodeUpdate(ntree, node);
@@ -3476,7 +3516,7 @@ static void rna_ShaderNodePointDensity_psys_set(PointerRNA *ptr,
NodeShaderTexPointDensity *shader_point_density = node->storage;
Object *ob = (Object *)node->id;
- if (ob && value.id.data == ob) {
+ if (ob && value.owner_id == &ob->id) {
shader_point_density->particle_system = BLI_findindex(&ob->particlesystem, value.data) + 1;
}
else {
@@ -3780,6 +3820,7 @@ static void def_group(StructRNA *srna)
RNA_def_property_pointer_funcs(
prop, NULL, "rna_NodeGroup_node_tree_set", NULL, "rna_NodeGroup_node_tree_poll");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Node Tree", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeGroup_update");
@@ -3852,7 +3893,7 @@ static void def_math(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, rna_enum_node_math_items);
RNA_def_property_ui_text(prop, "Operation", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
prop = RNA_def_property(srna, "use_clamp", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_MATH_CLAMP);
@@ -3868,7 +3909,7 @@ static void def_vector_math(StructRNA *srna)
RNA_def_property_enum_sdna(prop, NULL, "custom1");
RNA_def_property_enum_items(prop, rna_enum_node_vec_math_items);
RNA_def_property_ui_text(prop, "Operation", "");
- RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
}
static void def_rgb_curve(StructRNA *srna)
@@ -3954,6 +3995,7 @@ static void def_texture(StructRNA *srna)
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Texture");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Texture", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -4152,6 +4194,7 @@ static void def_sh_tex_environment(StructRNA *srna)
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Image");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Image", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_tex_image_update");
@@ -4230,6 +4273,7 @@ static void def_sh_tex_image(StructRNA *srna)
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Image");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Image", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_tex_image_update");
@@ -4464,6 +4508,18 @@ static void def_sh_tex_wave(StructRNA *srna)
RNA_def_property_update(prop, 0, "rna_Node_update");
}
+static void def_sh_tex_white_noise(StructRNA *srna)
+{
+ PropertyRNA *prop;
+
+ prop = RNA_def_property(srna, "dimensions", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "custom1");
+ RNA_def_property_enum_items(prop, rna_enum_node_tex_dimensions_items);
+ RNA_def_property_ui_text(
+ prop, "Dimensions", "The number of dimensions to evaluate the noise in");
+ RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNode_socket_update");
+}
+
static void def_sh_tex_coord(StructRNA *srna)
{
PropertyRNA *prop;
@@ -4472,6 +4528,7 @@ static void def_sh_tex_coord(StructRNA *srna)
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Object", "Use coordinates from this object (for object texture coordinates output)");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update_relations");
@@ -4606,6 +4663,7 @@ static void def_sh_tex_pointdensity(StructRNA *srna)
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Object", "Object to take point data from");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -5459,6 +5517,7 @@ static void def_cmp_image(StructRNA *srna)
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "Image");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Image", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Image_Node_update_id");
@@ -5486,6 +5545,7 @@ static void def_cmp_render_layers(StructRNA *srna)
RNA_def_property_pointer_funcs(prop, NULL, "rna_Node_scene_set", NULL, NULL);
RNA_def_property_struct_type(prop, "Scene");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Scene", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_view_layer_update");
@@ -6172,6 +6232,7 @@ static void def_cmp_defocus(StructRNA *srna)
RNA_def_property_pointer_funcs(prop, NULL, "rna_Node_scene_set", NULL, NULL);
RNA_def_property_struct_type(prop, "Scene");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Scene", "Scene from which to select the active camera (render scene if undefined)");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
@@ -6672,7 +6733,7 @@ static void def_cmp_colorbalance(StructRNA *srna)
RNA_def_property_float_sdna(prop, NULL, "offset");
RNA_def_property_array(prop, 3);
RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
- RNA_def_property_ui_text(prop, "Offset", "Correction for Shadows");
+ RNA_def_property_ui_text(prop, "Offset", "Correction for entire tonal range");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeColorBalance_update_cdl");
prop = RNA_def_property(srna, "power", PROP_FLOAT, PROP_COLOR_GAMMA);
@@ -7800,10 +7861,10 @@ static void rna_def_node_socket(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Type", "Data type");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
- prop = RNA_def_property(srna, "draw_shape", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "draw_shape");
- RNA_def_property_enum_items(prop, rna_enum_node_socket_draw_shape_items);
- RNA_def_property_enum_default(prop, SOCK_DRAW_SHAPE_CIRCLE);
+ prop = RNA_def_property(srna, "display_shape", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "display_shape");
+ RNA_def_property_enum_items(prop, rna_enum_node_socket_display_shape_items);
+ RNA_def_property_enum_default(prop, SOCK_DISPLAY_SHAPE_CIRCLE);
RNA_def_property_ui_text(prop, "Shape", "Socket shape");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocket_update");
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index a12f45732d6..c9061c7c087 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -299,27 +299,27 @@ const EnumPropertyItem rna_enum_object_axis_items[] = {
static void rna_Object_internal_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_TRANSFORM);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM);
}
static void rna_Object_internal_update_draw(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_TRANSFORM);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->id.data);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->owner_id);
}
static void rna_Object_matrix_world_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
/* don't use compat so we get predictable rotation */
- BKE_object_apply_mat4(ptr->id.data, ((Object *)ptr->id.data)->obmat, false, true);
+ BKE_object_apply_mat4((Object *)ptr->owner_id, ((Object *)ptr->owner_id)->obmat, false, true);
rna_Object_internal_update(bmain, scene, ptr);
}
static void rna_Object_hide_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
BKE_main_collection_sync_remap(bmain);
DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
DEG_relations_tag_update(bmain);
@@ -328,7 +328,7 @@ static void rna_Object_hide_update(Main *bmain, Scene *UNUSED(scene), PointerRNA
static void rna_MaterialIndex_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
if (ob && ob->type == OB_GPENCIL) {
/* notifying material property in topbar */
WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
@@ -337,13 +337,13 @@ static void rna_MaterialIndex_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
static void rna_Object_matrix_local_get(PointerRNA *ptr, float values[16])
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
BKE_object_matrix_local_get(ob, (float(*)[4])values);
}
static void rna_Object_matrix_local_set(PointerRNA *ptr, const float values[16])
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
float local_mat[4][4];
/* Localspace matrix is truly relative to the parent,
@@ -365,20 +365,20 @@ static void rna_Object_matrix_local_set(PointerRNA *ptr, const float values[16])
static void rna_Object_matrix_basis_get(PointerRNA *ptr, float values[16])
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
BKE_object_to_mat4(ob, (float(*)[4])values);
}
static void rna_Object_matrix_basis_set(PointerRNA *ptr, const float values[16])
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
BKE_object_apply_mat4(ob, (float(*)[4])values, false, false);
}
void rna_Object_internal_update_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->id.data);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ptr->owner_id);
}
void rna_Object_internal_update_data_dependency(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -389,7 +389,7 @@ void rna_Object_internal_update_data_dependency(Main *bmain, Scene *scene, Point
static void rna_Object_active_shape_update(bContext *C, PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
@@ -403,7 +403,7 @@ static void rna_Object_active_shape_update(bContext *C, PointerRNA *ptr)
DEG_id_tag_update(ob->data, 0);
EDBM_mesh_normals_update(((Mesh *)ob->data)->edit_mesh);
- BKE_editmesh_tessface_calc(((Mesh *)ob->data)->edit_mesh);
+ BKE_editmesh_looptri_calc(((Mesh *)ob->data)->edit_mesh);
break;
case OB_CURVE:
case OB_SURF:
@@ -422,9 +422,9 @@ static void rna_Object_active_shape_update(bContext *C, PointerRNA *ptr)
static void rna_Object_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_TRANSFORM);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_TRANSFORM);
DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->id.data);
+ WM_main_add_notifier(NC_OBJECT | ND_PARENT, ptr->owner_id);
}
static void rna_Object_data_set(PointerRNA *ptr, PointerRNA value, struct ReportList *reports)
@@ -546,27 +546,27 @@ static void rna_Object_parent_set(PointerRNA *ptr,
}
}
-bool rna_Object_parent_override_apply(Main *UNUSED(bmain),
- PointerRNA *ptr_dst,
- PointerRNA *ptr_src,
- PointerRNA *ptr_storage,
- PropertyRNA *prop_dst,
- PropertyRNA *prop_src,
- PropertyRNA *UNUSED(prop_storage),
- const int len_dst,
- const int len_src,
- const int len_storage,
- PointerRNA *UNUSED(ptr_item_dst),
- PointerRNA *UNUSED(ptr_item_src),
- PointerRNA *UNUSED(ptr_item_storage),
- IDOverrideLibraryPropertyOperation *opop)
+static bool rna_Object_parent_override_apply(Main *UNUSED(bmain),
+ PointerRNA *ptr_dst,
+ PointerRNA *ptr_src,
+ PointerRNA *ptr_storage,
+ PropertyRNA *prop_dst,
+ PropertyRNA *prop_src,
+ PropertyRNA *UNUSED(prop_storage),
+ const int len_dst,
+ const int len_src,
+ const int len_storage,
+ PointerRNA *UNUSED(ptr_item_dst),
+ PointerRNA *UNUSED(ptr_item_src),
+ PointerRNA *UNUSED(ptr_item_storage),
+ IDOverrideLibraryPropertyOperation *opop)
{
BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage) && len_dst == 0);
BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE &&
- "Unsupported RNA override operation on animdata pointer");
+ "Unsupported RNA override operation on object parent pointer");
UNUSED_VARS_NDEBUG(ptr_storage, len_dst, len_src, len_storage, opop);
- /* We need a special handling here because setting parent resets pinvert parent matrix,
+ /* We need a special handling here because setting parent resets invert parent matrix,
* which is evil in our case. */
Object *ob = (Object *)ptr_dst->data;
Object *parent_dst = RNA_property_pointer_get(ptr_dst, prop_dst).data;
@@ -691,7 +691,7 @@ static void rna_Object_dup_collection_set(PointerRNA *ptr,
static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bDeformGroup *dg = (bDeformGroup *)ptr->data;
BLI_strncpy_utf8(dg->name, value, sizeof(dg->name));
defgroup_unique_name(dg, ob);
@@ -699,34 +699,34 @@ static void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value)
static int rna_VertexGroup_index_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return BLI_findindex(&ob->defbase, ptr->data);
}
static PointerRNA rna_Object_active_vertex_group_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return rna_pointer_inherit_refine(
ptr, &RNA_VertexGroup, BLI_findlink(&ob->defbase, ob->actdef - 1));
}
static int rna_Object_active_vertex_group_index_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return ob->actdef - 1;
}
static void rna_Object_active_vertex_group_index_set(PointerRNA *ptr, int value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ob->actdef = value + 1;
}
static void rna_Object_active_vertex_group_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
*min = 0;
*max = max_ii(0, BLI_listbase_count(&ob->defbase) - 1);
@@ -734,7 +734,7 @@ static void rna_Object_active_vertex_group_index_range(
void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bDeformGroup *dg;
dg = BLI_findlink(&ob->defbase, index - 1);
@@ -749,7 +749,7 @@ void rna_object_vgroup_name_index_get(PointerRNA *ptr, char *value, int index)
int rna_object_vgroup_name_index_length(PointerRNA *ptr, int index)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bDeformGroup *dg;
dg = BLI_findlink(&ob->defbase, index - 1);
@@ -758,13 +758,13 @@ int rna_object_vgroup_name_index_length(PointerRNA *ptr, int index)
void rna_object_vgroup_name_index_set(PointerRNA *ptr, const char *value, short *index)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
*index = defgroup_name_index(ob, value) + 1;
}
void rna_object_vgroup_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bDeformGroup *dg = defgroup_find_name(ob, value);
if (dg) {
/* No need for BLI_strncpy_utf8, since this matches an existing group. */
@@ -777,7 +777,7 @@ void rna_object_vgroup_name_set(PointerRNA *ptr, const char *value, char *result
static void rna_FaceMap_name_set(PointerRNA *ptr, const char *value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bFaceMap *fmap = (bFaceMap *)ptr->data;
BLI_strncpy_utf8(fmap->name, value, sizeof(fmap->name));
BKE_object_facemap_unique_name(ob, fmap);
@@ -785,33 +785,33 @@ static void rna_FaceMap_name_set(PointerRNA *ptr, const char *value)
static int rna_FaceMap_index_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return BLI_findindex(&ob->fmaps, ptr->data);
}
static PointerRNA rna_Object_active_face_map_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return rna_pointer_inherit_refine(ptr, &RNA_FaceMap, BLI_findlink(&ob->fmaps, ob->actfmap - 1));
}
static int rna_Object_active_face_map_index_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return ob->actfmap - 1;
}
static void rna_Object_active_face_map_index_set(PointerRNA *ptr, int value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ob->actfmap = value + 1;
}
static void rna_Object_active_face_map_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
*min = 0;
*max = max_ii(0, BLI_listbase_count(&ob->fmaps) - 1);
@@ -819,7 +819,7 @@ static void rna_Object_active_face_map_index_range(
void rna_object_BKE_object_facemap_name_index_get(PointerRNA *ptr, char *value, int index)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bFaceMap *fmap;
fmap = BLI_findlink(&ob->fmaps, index - 1);
@@ -834,7 +834,7 @@ void rna_object_BKE_object_facemap_name_index_get(PointerRNA *ptr, char *value,
int rna_object_BKE_object_facemap_name_index_length(PointerRNA *ptr, int index)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bFaceMap *fmap;
fmap = BLI_findlink(&ob->fmaps, index - 1);
@@ -843,13 +843,13 @@ int rna_object_BKE_object_facemap_name_index_length(PointerRNA *ptr, int index)
void rna_object_BKE_object_facemap_name_index_set(PointerRNA *ptr, const char *value, short *index)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
*index = BKE_object_facemap_name_index(ob, value) + 1;
}
void rna_object_fmap_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bFaceMap *fmap = BKE_object_facemap_find_name(ob, value);
if (fmap) {
/* No need for BLI_strncpy_utf8, since this matches an existing group. */
@@ -862,7 +862,7 @@ void rna_object_fmap_name_set(PointerRNA *ptr, const char *value, char *result,
void rna_object_uvlayer_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Mesh *me;
CustomDataLayer *layer;
int a;
@@ -885,7 +885,7 @@ void rna_object_uvlayer_name_set(PointerRNA *ptr, const char *value, char *resul
void rna_object_vcollayer_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Mesh *me;
CustomDataLayer *layer;
int a;
@@ -908,13 +908,13 @@ void rna_object_vcollayer_name_set(PointerRNA *ptr, const char *value, char *res
static int rna_Object_active_material_index_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return MAX2(ob->actcol - 1, 0);
}
static void rna_Object_active_material_index_set(PointerRNA *ptr, int value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ob->actcol = value + 1;
if (ob->type == OB_MESH) {
@@ -929,7 +929,7 @@ static void rna_Object_active_material_index_set(PointerRNA *ptr, int value)
static void rna_Object_active_material_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
*min = 0;
*max = max_ii(ob->totcol - 1, 0);
}
@@ -937,7 +937,7 @@ static void rna_Object_active_material_index_range(
/* returns active base material */
static PointerRNA rna_Object_active_material_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Material *ma;
ma = (ob->totcol) ? give_current_material(ob, ob->actcol) : NULL;
@@ -948,7 +948,7 @@ static void rna_Object_active_material_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
DEG_id_tag_update(value.data, 0);
BLI_assert(BKE_id_is_in_global_main(&ob->id));
@@ -963,7 +963,7 @@ static void rna_Object_active_material_set(PointerRNA *ptr,
static int rna_Object_active_material_editable(PointerRNA *ptr, const char **UNUSED(r_info))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bool is_editable;
if ((ob->matbits == NULL) || (ob->actcol == 0) || ob->matbits[ob->actcol - 1]) {
@@ -979,20 +979,20 @@ static int rna_Object_active_material_editable(PointerRNA *ptr, const char **UNU
static void rna_Object_active_particle_system_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
*min = 0;
*max = max_ii(0, BLI_listbase_count(&ob->particlesystem) - 1);
}
static int rna_Object_active_particle_system_index_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return psys_get_current_num(ob);
}
static void rna_Object_active_particle_system_index_set(PointerRNA *ptr, int value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
psys_set_current_num(ob, value);
}
@@ -1000,7 +1000,7 @@ static void rna_Object_particle_update(Main *UNUSED(bmain), Scene *scene, Pointe
{
/* TODO: Disabled for now, because bContext is not available. */
# if 0
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
PE_current_changed(NULL, scene, ob);
# else
(void)scene;
@@ -1137,7 +1137,7 @@ static int rna_Object_rotation_4d_editable(PointerRNA *ptr, int index)
static int rna_MaterialSlot_material_editable(PointerRNA *ptr, const char **UNUSED(r_info))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
const int index = (Material **)ptr->data - ob->mat;
bool is_editable;
@@ -1153,7 +1153,7 @@ static int rna_MaterialSlot_material_editable(PointerRNA *ptr, const char **UNUS
static PointerRNA rna_MaterialSlot_material_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Material *ma;
const int index = (Material **)ptr->data - ob->mat;
@@ -1165,7 +1165,7 @@ static void rna_MaterialSlot_material_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
int index = (Material **)ptr->data - ob->mat;
BLI_assert(BKE_id_is_in_global_main(&ob->id));
@@ -1175,7 +1175,7 @@ static void rna_MaterialSlot_material_set(PointerRNA *ptr,
static bool rna_MaterialSlot_material_poll(PointerRNA *ptr, PointerRNA value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Material *ma = (Material *)value.data;
if (ob->type == OB_GPENCIL) {
@@ -1190,7 +1190,7 @@ static bool rna_MaterialSlot_material_poll(PointerRNA *ptr, PointerRNA value)
static int rna_MaterialSlot_link_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
int index = (Material **)ptr->data - ob->mat;
return ob->matbits[index] != 0;
@@ -1198,7 +1198,7 @@ static int rna_MaterialSlot_link_get(PointerRNA *ptr)
static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
int index = (Material **)ptr->data - ob->mat;
if (value) {
@@ -1213,7 +1213,7 @@ static void rna_MaterialSlot_link_set(PointerRNA *ptr, int value)
static int rna_MaterialSlot_name_length(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Material *ma;
int index = (Material **)ptr->data - ob->mat;
@@ -1228,7 +1228,7 @@ static int rna_MaterialSlot_name_length(PointerRNA *ptr)
static void rna_MaterialSlot_name_get(PointerRNA *ptr, char *str)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Material *ma;
int index = (Material **)ptr->data - ob->mat;
@@ -1246,14 +1246,14 @@ static void rna_MaterialSlot_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
rna_Object_internal_update(bmain, scene, ptr);
- WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, ptr->id.data);
+ WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, ptr->owner_id);
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL);
DEG_relations_tag_update(bmain);
}
static char *rna_MaterialSlot_path(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
int index = (Material **)ptr->data - ob->mat;
return BLI_sprintfN("material_slots[%d]", index);
@@ -1271,7 +1271,7 @@ static char *rna_ObjectDisplay_path(PointerRNA *UNUSED(ptr))
static PointerRNA rna_Object_active_particle_system_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleSystem *psys = psys_get_current(ob);
return rna_pointer_inherit_refine(ptr, &RNA_ParticleSystem, psys);
}
@@ -1279,7 +1279,7 @@ static PointerRNA rna_Object_active_particle_system_get(PointerRNA *ptr)
static void rna_Object_active_shape_key_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Key *key = BKE_key_from_object(ob);
*min = 0;
@@ -1296,21 +1296,21 @@ static void rna_Object_active_shape_key_index_range(
static int rna_Object_active_shape_key_index_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
return MAX2(ob->shapenr - 1, 0);
}
static void rna_Object_active_shape_key_index_set(PointerRNA *ptr, int value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ob->shapenr = value + 1;
}
static PointerRNA rna_Object_active_shape_key_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
Key *key = BKE_key_from_object(ob);
KeyBlock *kb;
PointerRNA keyptr;
@@ -1326,7 +1326,7 @@ static PointerRNA rna_Object_active_shape_key_get(PointerRNA *ptr)
static PointerRNA rna_Object_field_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
/* weak */
if (!ob->pd) {
@@ -1338,7 +1338,7 @@ static PointerRNA rna_Object_field_get(PointerRNA *ptr)
static PointerRNA rna_Object_collision_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
if (ob->type != OB_MESH) {
return PointerRNA_NULL;
@@ -1354,7 +1354,7 @@ static PointerRNA rna_Object_collision_get(PointerRNA *ptr)
static PointerRNA rna_Object_active_constraint_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bConstraint *con = BKE_constraints_active_get(&ob->constraints);
return rna_pointer_inherit_refine(ptr, &RNA_Constraint, con);
}
@@ -1363,7 +1363,7 @@ static void rna_Object_active_constraint_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
BKE_constraints_active_set(&ob->constraints, (bConstraint *)value.data);
}
@@ -1428,12 +1428,12 @@ bool rna_Object_constraints_override_apply(Main *UNUSED(bmain),
BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_INSERT_AFTER &&
"Unsupported RNA override operation on constraints collection");
- Object *ob_dst = (Object *)ptr_dst->id.data;
- Object *ob_src = (Object *)ptr_src->id.data;
+ Object *ob_dst = (Object *)ptr_dst->owner_id;
+ Object *ob_src = (Object *)ptr_src->owner_id;
/* Remember that insertion operations are defined and stored in correct order, which means that
- * even if we insert several items in a row, we alays insert first one, then second one, etc.
- * So we should always find 'anchor' constraint in both _src *and* _dst> */
+ * even if we insert several items in a row, we always insert first one, then second one, etc.
+ * So we should always find 'anchor' constraint in both _src *and* _dst. */
bConstraint *con_anchor = NULL;
if (opop->subitem_local_name && opop->subitem_local_name[0]) {
con_anchor = BLI_findstring(
@@ -1516,12 +1516,12 @@ bool rna_Object_modifiers_override_apply(Main *UNUSED(bmain),
BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_INSERT_AFTER &&
"Unsupported RNA override operation on modifiers collection");
- Object *ob_dst = (Object *)ptr_dst->id.data;
- Object *ob_src = (Object *)ptr_src->id.data;
+ Object *ob_dst = (Object *)ptr_dst->owner_id;
+ Object *ob_src = (Object *)ptr_src->owner_id;
/* Remember that insertion operations are defined and stored in correct order, which means that
- * even if we insert several items in a row, we alays insert first one, then second one, etc.
- * So we should always find 'anchor' constraint in both _src *and* _dst> */
+ * even if we insert several items in a row, we always insert first one, then second one, etc.
+ * So we should always find 'anchor' constraint in both _src *and* _dst. */
ModifierData *mod_anchor = NULL;
if (opop->subitem_local_name && opop->subitem_local_name[0]) {
mod_anchor = BLI_findstring(
@@ -1619,7 +1619,7 @@ static void rna_Object_shaderfx_clear(Object *object, bContext *C)
static void rna_Object_boundbox_get(PointerRNA *ptr, float *values)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
BoundBox *bb = BKE_object_boundbox_get(ob);
if (bb) {
memcpy(values, bb->vec, sizeof(bb->vec));
@@ -1791,42 +1791,42 @@ static void rna_FaceMap_face_remove(
/* generic poll functions */
bool rna_Lattice_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
- return ((Object *)value.id.data)->type == OB_LATTICE;
+ return ((Object *)value.owner_id)->type == OB_LATTICE;
}
bool rna_Curve_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
- return ((Object *)value.id.data)->type == OB_CURVE;
+ return ((Object *)value.owner_id)->type == OB_CURVE;
}
bool rna_Armature_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
- return ((Object *)value.id.data)->type == OB_ARMATURE;
+ return ((Object *)value.owner_id)->type == OB_ARMATURE;
}
bool rna_Mesh_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
- return ((Object *)value.id.data)->type == OB_MESH;
+ return ((Object *)value.owner_id)->type == OB_MESH;
}
bool rna_Camera_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
- return ((Object *)value.id.data)->type == OB_CAMERA;
+ return ((Object *)value.owner_id)->type == OB_CAMERA;
}
bool rna_Light_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
- return ((Object *)value.id.data)->type == OB_LAMP;
+ return ((Object *)value.owner_id)->type == OB_LAMP;
}
bool rna_GPencil_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
- return ((Object *)value.id.data)->type == OB_GPENCIL;
+ return ((Object *)value.owner_id)->type == OB_GPENCIL;
}
int rna_Object_use_dynamic_topology_sculpting_get(PointerRNA *ptr)
{
- SculptSession *ss = ((Object *)ptr->id.data)->sculpt;
+ SculptSession *ss = ((Object *)ptr->owner_id)->sculpt;
return (ss && ss->bm);
}
@@ -2509,10 +2509,12 @@ static void rna_def_object(BlenderRNA *brna)
/* proxy */
prop = RNA_def_property(srna, "proxy", PROP_POINTER, PROP_NONE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
RNA_def_property_ui_text(prop, "Proxy", "Library object this proxy object controls");
prop = RNA_def_property(srna, "proxy_collection", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "proxy_group");
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
RNA_def_property_ui_text(
prop, "Proxy Collection", "Library collection duplicator object this proxy object controls");
@@ -2848,6 +2850,14 @@ static void rna_def_object(BlenderRNA *brna)
prop, "Display in Orthographic Mode", "Display image in orthographic mode");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ prop = RNA_def_property(srna, "show_empty_image_only_axis_aligned", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(
+ prop, NULL, "empty_image_visibility_flag", OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED);
+ RNA_def_property_ui_text(prop,
+ "Display Only Axis Aligned",
+ "Only display the image when it is aligned with the view axis");
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
prop = RNA_def_property(srna, "use_empty_image_alpha", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "empty_image_flag", OB_EMPTY_IMAGE_USE_ALPHA_BLEND);
RNA_def_property_ui_text(
@@ -2878,7 +2888,7 @@ static void rna_def_object(BlenderRNA *brna)
prop = RNA_def_property(srna, "color", PROP_FLOAT, PROP_COLOR);
RNA_def_property_ui_text(
prop, "Color", "Object color and alpha, used when faces have the ObColor mode enabled");
- RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+ RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw");
/* physics */
prop = RNA_def_property(srna, "field", PROP_POINTER, PROP_NONE);
@@ -2983,6 +2993,7 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_pointer_sdna(prop, NULL, "instance_collection");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_pointer_funcs(prop, NULL, "rna_Object_dup_collection_set", NULL, NULL);
RNA_def_property_ui_text(prop, "Instance Collection", "Instance an existing collection");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_dependency_update");
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 3f0b5546a03..5bec6f0c7d3 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -244,7 +244,7 @@ static Base *rna_Object_local_view_property_helper(
static bool rna_Object_local_view_get(Object *ob, ReportList *reports, PointerRNA *v3d_ptr)
{
- bScreen *sc = v3d_ptr->id.data;
+ bScreen *sc = (bScreen *)v3d_ptr->owner_id;
View3D *v3d = v3d_ptr->data;
Base *base = rna_Object_local_view_property_helper(sc, v3d, ob, reports, NULL);
if (base == NULL) {
@@ -258,7 +258,7 @@ static void rna_Object_local_view_set(Object *ob,
PointerRNA *v3d_ptr,
bool state)
{
- bScreen *sc = v3d_ptr->id.data;
+ bScreen *sc = (bScreen *)v3d_ptr->owner_id;
View3D *v3d = v3d_ptr->data;
Scene *scene;
Base *base = rna_Object_local_view_property_helper(sc, v3d, ob, reports, &scene);
@@ -704,7 +704,7 @@ bool rna_Object_generate_gpencil_strokes(Object *ob,
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, gpencil_lines, use_collections);
+ BKE_gpencil_convert_curve(bmain, scene, ob_gpencil, ob, gpencil_lines, use_collections, false);
WM_main_add_notifier(NC_GPENCIL | ND_DATA, NULL);
diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c
index 066e350ab3e..430059c7a18 100644
--- a/source/blender/makesrna/intern/rna_object_force.c
+++ b/source/blender/makesrna/intern/rna_object_force.c
@@ -87,15 +87,15 @@ static const EnumPropertyItem empty_shape_items[] = {
static const EnumPropertyItem vortex_shape_items[] = {
{PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""},
{PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""},
- {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Surface falloff (New)", ""},
- {PFIELD_SHAPE_POINTS, "POINTS", 0, "Every Point (New)", ""},
+ {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Surface", ""},
+ {PFIELD_SHAPE_POINTS, "POINTS", 0, "Every Point", ""},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem curve_vortex_shape_items[] = {
{PFIELD_SHAPE_POINT, "POINT", 0, "Point", ""},
{PFIELD_SHAPE_PLANE, "PLANE", 0, "Plane", ""},
- {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Curve (New)", ""},
+ {PFIELD_SHAPE_SURFACE, "SURFACE", 0, "Curve", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -120,18 +120,38 @@ static const EnumPropertyItem empty_vortex_shape_items[] = {
# include "ED_object.h"
+static bool rna_Cache_get_valid_owner_ID(PointerRNA *ptr, Object **ob, Scene **scene)
+{
+ switch (GS(ptr->owner_id->name)) {
+ case ID_OB:
+ *ob = (Object *)ptr->owner_id;
+ break;
+ case ID_SCE:
+ *scene = (Scene *)ptr->owner_id;
+ break;
+ default:
+ BLI_assert(!"Trying to get PTCacheID from an invalid ID type "
+ "(Only scenes and objects are supported).");
+ break;
+ }
+
+ return (*ob != NULL || *scene != NULL);
+}
+
static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
- PointCache *cache = (PointCache *)ptr->data;
+ Object *ob = NULL;
+ Scene *scene = NULL;
- if (!ob) {
+ if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return;
}
+ PointCache *cache = (PointCache *)ptr->data;
+
cache->flag |= PTCACHE_OUTDATED;
- PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
@@ -146,14 +166,16 @@ static void rna_Cache_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
static void rna_Cache_toggle_disk_cache(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
- PointCache *cache = (PointCache *)ptr->data;
+ Object *ob = NULL;
+ Scene *scene = NULL;
- if (!ob) {
+ if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return;
}
- PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
+ PointCache *cache = (PointCache *)ptr->data;
+
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
/* smoke can only use disk cache */
if (pid.cache && pid.type != PTCACHE_TYPE_SMOKE_DOMAIN) {
@@ -166,18 +188,20 @@ static void rna_Cache_toggle_disk_cache(Main *UNUSED(bmain), Scene *UNUSED(scene
static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
- PointCache *cache = (PointCache *)ptr->data;
- bool use_new_name = true;
+ Object *ob = NULL;
+ Scene *scene = NULL;
- if (!ob) {
+ if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return;
}
+ PointCache *cache = (PointCache *)ptr->data;
+ bool use_new_name = true;
+
/* TODO: check for proper characters */
if (cache->flag & PTCACHE_EXTERNAL) {
- PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
if (pid.cache) {
BKE_ptcache_load_external(&pid);
@@ -190,7 +214,7 @@ static void rna_Cache_idname_change(Main *UNUSED(bmain), Scene *UNUSED(scene), P
PTCacheID *pid = NULL, *pid2 = NULL;
ListBase pidlist;
- BKE_ptcache_ids_from_object(&pidlist, ob, NULL, 0);
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
for (pid = pidlist.first; pid; pid = pid->next) {
if (pid->cache == cache) {
@@ -240,13 +264,19 @@ static void rna_Cache_list_begin(CollectionPropertyIterator *iter, PointerRNA *p
static void rna_Cache_active_point_cache_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Object *ob = ptr->id.data;
- PointCache *cache = ptr->data;
- PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
-
*min = 0;
*max = 0;
+ Object *ob = NULL;
+ Scene *scene = NULL;
+
+ if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
+ return;
+ }
+
+ PointCache *cache = ptr->data;
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
+
if (pid.cache) {
*max = max_ii(0, BLI_listbase_count(pid.ptcaches) - 1);
}
@@ -254,11 +284,18 @@ static void rna_Cache_active_point_cache_index_range(
static int rna_Cache_active_point_cache_index_get(PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
- PointCache *cache = ptr->data;
- PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
int num = 0;
+ Object *ob = NULL;
+ Scene *scene = NULL;
+
+ if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
+ return num;
+ }
+
+ PointCache *cache = ptr->data;
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
+
if (pid.cache) {
num = BLI_findindex(pid.ptcaches, cache);
}
@@ -268,9 +305,15 @@ static int rna_Cache_active_point_cache_index_get(PointerRNA *ptr)
static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int value)
{
- Object *ob = ptr->id.data;
+ Object *ob = NULL;
+ Scene *scene = NULL;
+
+ if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
+ return;
+ }
+
PointCache *cache = ptr->data;
- PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
if (pid.cache) {
*(pid.cache_ptr) = BLI_findlink(pid.ptcaches, value);
@@ -280,13 +323,19 @@ static void rna_Cache_active_point_cache_index_set(struct PointerRNA *ptr, int v
static void rna_PointCache_frame_step_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Object *ob = ptr->id.data;
- PointCache *cache = ptr->data;
- PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
-
*min = 1;
*max = 20;
+ Object *ob = NULL;
+ Scene *scene = NULL;
+
+ if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
+ return;
+ }
+
+ PointCache *cache = ptr->data;
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
+
if (pid.cache) {
*max = pid.max_step;
}
@@ -294,14 +343,16 @@ static void rna_PointCache_frame_step_range(
int rna_Cache_info_length(PointerRNA *ptr)
{
- PointCache *cache = (PointCache *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = NULL;
+ Scene *scene = NULL;
- if (!ob) {
+ if (!rna_Cache_get_valid_owner_ID(ptr, &ob, &scene)) {
return 0;
}
- PTCacheID pid = BKE_ptcache_id_find(ob, NULL, cache);
+ PointCache *cache = (PointCache *)ptr->data;
+
+ PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
if (cache->flag & PTCACHE_FLAG_INFO_DIRTY) {
BKE_ptcache_update_info(&pid);
@@ -314,7 +365,7 @@ static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr))
{
/* both methods work ok, but return the shorter path */
# if 0
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ModifierData *md = (ModifierData *)modifiers_findByType(ob, eModifierType_Collision);
if (md) {
@@ -334,13 +385,13 @@ static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr))
static bool rna_SoftBodySettings_use_edges_get(PointerRNA *ptr)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
return (((data->softflag) & OB_SB_EDGES) != 0);
}
static void rna_SoftBodySettings_use_edges_set(PointerRNA *ptr, bool value)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
if (value) {
data->softflag |= OB_SB_EDGES;
}
@@ -351,13 +402,13 @@ static void rna_SoftBodySettings_use_edges_set(PointerRNA *ptr, bool value)
static bool rna_SoftBodySettings_use_goal_get(PointerRNA *ptr)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
return (((data->softflag) & OB_SB_GOAL) != 0);
}
static void rna_SoftBodySettings_use_goal_set(PointerRNA *ptr, bool value)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
if (value) {
data->softflag |= OB_SB_GOAL;
}
@@ -368,13 +419,13 @@ static void rna_SoftBodySettings_use_goal_set(PointerRNA *ptr, bool value)
static bool rna_SoftBodySettings_stiff_quads_get(PointerRNA *ptr)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
return (((data->softflag) & OB_SB_QUADS) != 0);
}
static void rna_SoftBodySettings_stiff_quads_set(PointerRNA *ptr, bool value)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
if (value) {
data->softflag |= OB_SB_QUADS;
}
@@ -385,13 +436,13 @@ static void rna_SoftBodySettings_stiff_quads_set(PointerRNA *ptr, bool value)
static bool rna_SoftBodySettings_self_collision_get(PointerRNA *ptr)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
return (((data->softflag) & OB_SB_SELF) != 0);
}
static void rna_SoftBodySettings_self_collision_set(PointerRNA *ptr, bool value)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
if (value) {
data->softflag |= OB_SB_SELF;
}
@@ -402,7 +453,7 @@ static void rna_SoftBodySettings_self_collision_set(PointerRNA *ptr, bool value)
static int rna_SoftBodySettings_new_aero_get(PointerRNA *ptr)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
if (data->softflag & OB_SB_AERO_ANGLE) {
return 1;
}
@@ -413,7 +464,7 @@ static int rna_SoftBodySettings_new_aero_get(PointerRNA *ptr)
static void rna_SoftBodySettings_new_aero_set(PointerRNA *ptr, int value)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
if (value == 1) {
data->softflag |= OB_SB_AERO_ANGLE;
}
@@ -424,13 +475,13 @@ static void rna_SoftBodySettings_new_aero_set(PointerRNA *ptr, int value)
static bool rna_SoftBodySettings_face_collision_get(PointerRNA *ptr)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
return (((data->softflag) & OB_SB_FACECOLL) != 0);
}
static void rna_SoftBodySettings_face_collision_set(PointerRNA *ptr, bool value)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
if (value) {
data->softflag |= OB_SB_FACECOLL;
}
@@ -441,13 +492,13 @@ static void rna_SoftBodySettings_face_collision_set(PointerRNA *ptr, bool value)
static bool rna_SoftBodySettings_edge_collision_get(PointerRNA *ptr)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
return (((data->softflag) & OB_SB_EDGECOLL) != 0);
}
static void rna_SoftBodySettings_edge_collision_set(PointerRNA *ptr, bool value)
{
- Object *data = (Object *)(ptr->id.data);
+ Object *data = (Object *)(ptr->owner_id);
if (value) {
data->softflag |= OB_SB_EDGECOLL;
}
@@ -488,7 +539,7 @@ static void rna_SoftBodySettings_spring_vgroup_set(PointerRNA *ptr, const char *
static char *rna_SoftBodySettings_path(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ModifierData *md = (ModifierData *)modifiers_findByType(ob, eModifierType_Softbody);
char name_esc[sizeof(md->name) * 2];
@@ -498,7 +549,7 @@ static char *rna_SoftBodySettings_path(PointerRNA *ptr)
static int particle_id_check(PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
return (GS(id->name) == ID_PA);
}
@@ -506,7 +557,7 @@ static int particle_id_check(PointerRNA *ptr)
static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
if (particle_id_check(ptr)) {
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
if (part->pd->forcefield != PFIELD_TEXTURE && part->pd->tex) {
id_us_min(&part->pd->tex->id);
@@ -524,7 +575,7 @@ static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
else {
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
if (ob->pd->forcefield != PFIELD_TEXTURE && ob->pd->tex) {
id_us_min(&ob->pd->tex->id);
@@ -539,7 +590,7 @@ static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene),
static void rna_FieldSettings_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
if (!particle_id_check(ptr)) {
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ED_object_check_force_modifiers(bmain, scene, ob);
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
@@ -555,7 +606,7 @@ static void rna_FieldSettings_type_set(PointerRNA *ptr, int value)
part_deflect->forcefield = value;
if (!particle_id_check(ptr)) {
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ob->pd->forcefield = value;
if (ELEM(value, PFIELD_WIND, PFIELD_VORTEX)) {
ob->empty_drawtype = OB_SINGLE_ARROW;
@@ -571,12 +622,12 @@ static void rna_FieldSettings_dependency_update(Main *bmain, Scene *scene, Point
DEG_relations_tag_update(bmain);
if (particle_id_check(ptr)) {
- DEG_id_tag_update((ID *)ptr->id.data,
+ DEG_id_tag_update(ptr->owner_id,
ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION |
ID_RECALC_PSYS_RESET);
}
else {
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
rna_FieldSettings_shape_update(bmain, scene, ptr);
@@ -599,7 +650,7 @@ static char *rna_FieldSettings_path(PointerRNA *ptr)
if (particle_id_check(ptr)) {
/* particle system force field */
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
if (part->pd == pd) {
return BLI_strdup("force_field_1");
@@ -610,7 +661,7 @@ static char *rna_FieldSettings_path(PointerRNA *ptr)
}
else {
/* object force field */
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
if (ob->pd == pd) {
return BLI_strdup("field");
@@ -621,7 +672,7 @@ static char *rna_FieldSettings_path(PointerRNA *ptr)
static void rna_EffectorWeight_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (id && GS(id->name) == ID_SCE) {
Scene *scene = (Scene *)id;
@@ -642,7 +693,7 @@ static void rna_EffectorWeight_dependency_update(Main *bmain,
{
DEG_relations_tag_update(bmain);
- DEG_id_tag_update((ID *)ptr->id.data, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY | ID_RECALC_PSYS_RESET);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL);
}
@@ -654,14 +705,14 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr)
if (particle_id_check(ptr)) {
/* particle effector weights */
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
if (part->effector_weights == ew) {
return BLI_strdup("effector_weights");
}
}
else {
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ModifierData *md;
/* check softbody modifier */
@@ -727,7 +778,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr)
static void rna_CollisionSettings_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ModifierData *md = modifiers_findByType(ob, eModifierType_Collision);
/* add/remove modifier as needed */
@@ -745,7 +796,7 @@ static void rna_CollisionSettings_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
@@ -753,7 +804,7 @@ static void rna_CollisionSettings_update(Main *UNUSED(bmain),
static void rna_softbody_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
@@ -776,7 +827,7 @@ static const EnumPropertyItem *rna_Effector_shape_itemf(bContext *UNUSED(C),
return empty_shape_items;
}
- ob = (Object *)ptr->id.data;
+ ob = (Object *)ptr->owner_id;
if (ob->type == OB_CURVE) {
if (ob->pd->forcefield == PFIELD_VORTEX) {
@@ -888,7 +939,7 @@ static void rna_def_pointcache_common(StructRNA *srna)
prop = RNA_def_property(srna, "info", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "info");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- /* Note that we do not actually need a getter here, `rna_Cache_info_length` will upate the info
+ /* Note that we do not actually need a getter here, `rna_Cache_info_length` will update the info
* string just as well. */
RNA_def_property_string_funcs(prop, NULL, "rna_Cache_info_length", NULL);
RNA_def_property_string_maxlength(
@@ -1262,13 +1313,17 @@ static void rna_def_field(BlenderRNA *brna)
ICON_FORCE_LENNARDJONES,
"Lennard-Jones",
"Forcefield based on the Lennard-Jones potential"},
- {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", "Forcefield based on a texture"},
+ {PFIELD_TEXTURE, "TEXTURE", ICON_FORCE_TEXTURE, "Texture", "Force field based on a texture"},
{PFIELD_GUIDE,
"GUIDE",
ICON_FORCE_CURVE,
"Curve Guide",
"Create a force along a curve object"},
- {PFIELD_BOID, "BOID", ICON_FORCE_BOID, "Boid", ""},
+ {PFIELD_BOID,
+ "BOID",
+ ICON_FORCE_BOID,
+ "Boid",
+ "Create a force that acts as a boid's predators or target"},
{PFIELD_TURBULENCE,
"TURBULENCE",
ICON_FORCE_TURBULENCE,
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 86ce0ade96b..98ecb053641 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -146,7 +146,7 @@ static void rna_ParticleHairKey_location_object_info(PointerRNA *ptr,
ParticleData **pa_pt)
{
HairKey *hkey = (HairKey *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ModifierData *md;
ParticleSystemModifierData *psmd = NULL;
ParticleSystem *psys;
@@ -193,7 +193,7 @@ static void rna_ParticleHairKey_location_object_info(PointerRNA *ptr,
static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *values)
{
HairKey *hkey = (HairKey *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleSystemModifierData *psmd;
ParticleData *pa;
@@ -221,7 +221,7 @@ static void rna_ParticleHairKey_location_object_get(PointerRNA *ptr, float *valu
static void rna_ParticleHairKey_location_object_set(PointerRNA *ptr, const float *values)
{
HairKey *hkey = (HairKey *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleSystemModifierData *psmd;
ParticleData *pa;
@@ -618,7 +618,7 @@ static void rna_ParticleSystem_mcol_on_emitter(ParticleSystem *particlesystem,
static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr, short flag)
{
if (ptr->type == &RNA_ParticleSystem) {
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleSystem *psys = (ParticleSystem *)ptr->data;
psys->recalc = flag;
@@ -626,7 +626,7 @@ static void particle_recalc(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
}
else {
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY | flag);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY | flag);
}
WM_main_add_notifier(NC_OBJECT | ND_PARTICLE | NA_EDITED, NULL);
@@ -663,7 +663,7 @@ static void rna_Particle_reset_dependency(Main *bmain, Scene *scene, PointerRNA
static void rna_Particle_change_type(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ParticleSettings *part = ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
/* Iterating over all object is slow, but no better solution exists at the moment. */
for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
@@ -716,7 +716,7 @@ static void rna_Particle_redo_child(Main *bmain, Scene *scene, PointerRNA *ptr)
static void rna_Particle_cloth_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ob);
@@ -741,7 +741,7 @@ static ParticleSystem *rna_particle_system_for_target(Object *ob, ParticleTarget
static void rna_Particle_target_reset(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
if (ptr->type == &RNA_ParticleTarget) {
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleTarget *pt = (ParticleTarget *)ptr->data;
ParticleSystem *kpsys = NULL, *psys = rna_particle_system_for_target(ob, pt);
@@ -780,7 +780,7 @@ static void rna_Particle_target_reset(Main *bmain, Scene *UNUSED(scene), Pointer
static void rna_Particle_target_redo(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
if (ptr->type == &RNA_ParticleTarget) {
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleTarget *pt = (ParticleTarget *)ptr->data;
ParticleSystem *psys = rna_particle_system_for_target(ob, pt);
@@ -793,7 +793,7 @@ static void rna_Particle_target_redo(Main *UNUSED(bmain), Scene *UNUSED(scene),
static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleSystem *psys = (ParticleSystem *)ptr->data;
if (psys && !psys->clmd) {
@@ -823,7 +823,7 @@ static void rna_particle_settings_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleSystem *psys = (ParticleSystem *)ptr->data;
int old_type = 0;
@@ -1000,7 +1000,7 @@ static void rna_ParticleSettings_use_twist_curve_update(Main *bmain, Scene *scen
static void rna_ParticleSystem_name_set(PointerRNA *ptr, const char *value)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleSystem *part = (ParticleSystem *)ptr->data;
/* copy the new name into the name slot */
@@ -1076,7 +1076,7 @@ static void rna_ParticleTarget_name_get(PointerRNA *ptr, char *str)
psys = BLI_findlink(&pt->ob->particlesystem, pt->psys - 1);
}
else {
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
psys = BLI_findlink(&ob->particlesystem, pt->psys - 1);
}
@@ -1108,7 +1108,7 @@ static int rna_ParticleTarget_name_length(PointerRNA *ptr)
static int particle_id_check(PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
return (GS(id->name) == ID_PA);
}
@@ -1118,7 +1118,7 @@ static char *rna_SPHFluidSettings_path(PointerRNA *ptr)
SPHFluidSettings *fluid = (SPHFluidSettings *)ptr->data;
if (particle_id_check(ptr)) {
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
if (part->fluid == fluid) {
return BLI_strdup("fluid");
@@ -1152,7 +1152,7 @@ static bool rna_ParticleSystem_edited_get(PointerRNA *ptr)
}
static PointerRNA rna_ParticleDupliWeight_active_get(PointerRNA *ptr)
{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
ParticleDupliWeight *dw = part->instance_weights.first;
for (; dw; dw = dw->next) {
@@ -1165,14 +1165,14 @@ static PointerRNA rna_ParticleDupliWeight_active_get(PointerRNA *ptr)
static void rna_ParticleDupliWeight_active_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
*min = 0;
*max = max_ii(0, BLI_listbase_count(&part->instance_weights) - 1);
}
static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr)
{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
ParticleDupliWeight *dw = part->instance_weights.first;
int i = 0;
@@ -1187,7 +1187,7 @@ static int rna_ParticleDupliWeight_active_index_get(PointerRNA *ptr)
static void rna_ParticleDupliWeight_active_index_set(struct PointerRNA *ptr, int value)
{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
ParticleDupliWeight *dw = part->instance_weights.first;
int i = 0;
@@ -1203,7 +1203,7 @@ 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;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
psys_find_group_weights(part);
ParticleDupliWeight *dw = ptr->data;
@@ -1241,7 +1241,7 @@ static const EnumPropertyItem *rna_Particle_dist_itemf(bContext *UNUSED(C),
PropertyRNA *UNUSED(prop),
bool *UNUSED(r_free))
{
- ParticleSettings *part = ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
if (part->type == PART_HAIR) {
return part_hair_dist_items;
@@ -1256,7 +1256,7 @@ static const EnumPropertyItem *rna_Particle_draw_as_itemf(bContext *UNUSED(C),
PropertyRNA *UNUSED(prop),
bool *UNUSED(r_free))
{
- ParticleSettings *part = ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
if (part->type == PART_HAIR) {
return part_hair_draw_as_items;
@@ -1271,7 +1271,7 @@ static const EnumPropertyItem *rna_Particle_ren_as_itemf(bContext *UNUSED(C),
PropertyRNA *UNUSED(prop),
bool *UNUSED(r_free))
{
- ParticleSettings *part = ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
if (part->type == PART_HAIR) {
return part_hair_ren_as_items;
@@ -1283,7 +1283,7 @@ static const EnumPropertyItem *rna_Particle_ren_as_itemf(bContext *UNUSED(C),
static PointerRNA rna_Particle_field1_get(PointerRNA *ptr)
{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
/* weak */
if (!part->pd) {
@@ -1295,7 +1295,7 @@ static PointerRNA rna_Particle_field1_get(PointerRNA *ptr)
static PointerRNA rna_Particle_field2_get(PointerRNA *ptr)
{
- ParticleSettings *part = (ParticleSettings *)ptr->id.data;
+ ParticleSettings *part = (ParticleSettings *)ptr->owner_id;
/* weak */
if (!part->pd2) {
@@ -1307,7 +1307,7 @@ static PointerRNA rna_Particle_field2_get(PointerRNA *ptr)
static void psys_vg_name_get__internal(PointerRNA *ptr, char *value, int index)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleSystem *psys = (ParticleSystem *)ptr->data;
if (psys->vgroup[index] > 0) {
@@ -1323,7 +1323,7 @@ static void psys_vg_name_get__internal(PointerRNA *ptr, char *value, int index)
}
static int psys_vg_name_len__internal(PointerRNA *ptr, int index)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleSystem *psys = (ParticleSystem *)ptr->data;
if (psys->vgroup[index] > 0) {
@@ -1337,7 +1337,7 @@ static int psys_vg_name_len__internal(PointerRNA *ptr, int index)
}
static void psys_vg_name_set__internal(PointerRNA *ptr, const char *value, int index)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
ParticleSystem *psys = (ParticleSystem *)ptr->data;
if (value[0] == '\0') {
@@ -2041,6 +2041,7 @@ static void rna_def_particle_settings_mtex(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "object");
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Object", "Object to use for mapping with Object texture coordinates");
RNA_def_property_update(prop, 0, "rna_Particle_reset_dependency");
@@ -2986,6 +2987,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_pointer_sdna(prop, NULL, "collision_group");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Collision Collection", "Limit colliders to this collection");
RNA_def_property_update(prop, 0, "rna_Particle_reset_dependency");
@@ -3313,6 +3315,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "instance_collection");
RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Dupli Collection", "Show Objects in this collection in place of particles");
RNA_def_property_update(prop, 0, "rna_Particle_redo_count");
@@ -3338,6 +3341,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "instance_object", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Instance Object", "Show this Object in place of particles");
RNA_def_property_update(prop, 0, "rna_Particle_redo_dependency");
@@ -3456,6 +3460,7 @@ static void rna_def_particle_target(BlenderRNA *brna)
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop,
"Target Object",
@@ -3570,6 +3575,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "reactor_target_object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "target_ob");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop,
"Reactor Target Object",
"For reactor systems, the object that has the target particle system "
@@ -3822,6 +3828,7 @@ static void rna_def_particle_system(BlenderRNA *brna)
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "parent");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Parent", "Use this object's coordinate system instead of global coordinate system");
RNA_def_property_update(prop, 0, "rna_Particle_redo");
diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c
index d359726b3bd..33d7d7d99cf 100644
--- a/source/blender/makesrna/intern/rna_pose.c
+++ b/source/blender/makesrna/intern/rna_pose.c
@@ -99,25 +99,25 @@ static void rna_Pose_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRN
{
/* XXX when to use this? ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); */
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->id.data);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->owner_id);
}
static void rna_Pose_dependency_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
DEG_relations_tag_update(bmain);
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->id.data);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->owner_id);
}
static void rna_Pose_IK_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
/* XXX when to use this? ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK); */
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->id.data);
+ WM_main_add_notifier(NC_OBJECT | ND_POSE, ptr->owner_id);
BIK_clear_data(ob->pose);
}
@@ -183,7 +183,7 @@ bool rna_ActionGroup_is_custom_colorset_get(PointerRNA *ptr)
static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bActionGroup *agrp = ptr->data;
/* copy the new name into the name slot */
@@ -227,7 +227,7 @@ static void rna_Pose_ik_solver_set(struct PointerRNA *ptr, int value)
static void rna_Pose_ik_solver_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bPose *pose = ptr->data;
BKE_pose_tag_recalc(bmain, pose); /* checks & sorts pose channels */
@@ -276,7 +276,7 @@ static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value)
static void rna_PoseChannel_name_set(PointerRNA *ptr, const char *value)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
char oldname[sizeof(pchan->name)], newname[sizeof(pchan->name)];
@@ -291,19 +291,19 @@ static void rna_PoseChannel_name_set(PointerRNA *ptr, const char *value)
static PointerRNA rna_PoseChannel_bone_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
PointerRNA tmp_ptr = *ptr;
/* Replace the id_data pointer with the Armature ID. */
- tmp_ptr.id.data = ob->data;
+ tmp_ptr.owner_id = ob->data;
return rna_pointer_inherit_refine(&tmp_ptr, &RNA_Bone, pchan->bone);
}
static bool rna_PoseChannel_has_ik_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
return BKE_pose_channel_in_IK_chain(ob, pchan);
@@ -341,7 +341,7 @@ static StructRNA *rna_Pose_ikparam_typef(PointerRNA *ptr)
static void rna_Itasc_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bItasc *itasc = ptr->data;
/* verify values */
@@ -373,7 +373,7 @@ static void rna_Itasc_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
static void rna_Itasc_update_rebuild(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bPose *pose = ob->pose;
BKE_pose_tag_recalc(bmain, pose); /* checks & sorts pose channels */
@@ -398,7 +398,7 @@ static void rna_PoseChannel_bone_custom_set(PointerRNA *ptr,
static PointerRNA rna_PoseChannel_bone_group_get(PointerRNA *ptr)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bPose *pose = (ob) ? ob->pose : NULL;
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
bActionGroup *grp;
@@ -417,7 +417,7 @@ static void rna_PoseChannel_bone_group_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bPose *pose = (ob) ? ob->pose : NULL;
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
@@ -444,7 +444,7 @@ static void rna_PoseChannel_bone_group_index_set(PointerRNA *ptr, int value)
static void rna_PoseChannel_bone_group_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bPose *pose = (ob) ? ob->pose : NULL;
*min = 0;
@@ -663,7 +663,7 @@ bool rna_PoseChannel_constraints_override_apply(Main *UNUSED(bmain),
static int rna_PoseChannel_proxy_editable(PointerRNA *ptr, const char **r_info)
{
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
bArmature *arm = ob->data;
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
@@ -762,7 +762,7 @@ static int rna_PoseBones_lookup_string(PointerRNA *ptr, const char *key, Pointer
bPose *pose = (bPose *)ptr->data;
bPoseChannel *pchan = BKE_pose_channel_find_name(pose, key);
if (pchan) {
- RNA_pointer_create(ptr->id.data, &RNA_PoseBone, pchan, r_ptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_PoseBone, pchan, r_ptr);
return true;
}
else {
@@ -785,7 +785,7 @@ static void rna_PoseChannel_matrix_basis_set(PointerRNA *ptr, const float *value
static void rna_PoseChannel_matrix_set(PointerRNA *ptr, const float *values)
{
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
float tmat[4][4];
BKE_armature_mat_pose_to_bone_ex(NULL, ob, pchan, (float(*)[4])values, tmat);
@@ -812,9 +812,9 @@ static void rna_PoseChannel_custom_shape_transform_set(PointerRNA *ptr,
struct ReportList *UNUSED(reports))
{
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
- pchan->custom_tx = rna_PoseChannel_ensure_own_pchan(ob, value.id.data, value.data);
+ pchan->custom_tx = rna_PoseChannel_ensure_own_pchan(ob, (Object *)value.owner_id, value.data);
}
#else
@@ -1044,7 +1044,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_update");
/* Curved bones settings - Applied on top of restpose values */
- rna_def_bone_curved_common(srna, true);
+ rna_def_bone_curved_common(srna, true, false);
/* Custom BBone next/prev sources */
prop = RNA_def_property(srna, "bbone_custom_handle_start", PROP_POINTER, PROP_NONE);
@@ -1256,6 +1256,7 @@ static void rna_def_pose_channel(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "custom");
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_NO_COMPARISON);
RNA_def_property_pointer_funcs(prop, NULL, "rna_PoseChannel_bone_custom_set", NULL, NULL);
RNA_def_property_ui_text(
prop, "Custom Object", "Object that defines custom draw type for this bone");
diff --git a/source/blender/makesrna/intern/rna_rigidbody.c b/source/blender/makesrna/intern/rna_rigidbody.c
index cb6776c2c06..03937a5434e 100644
--- a/source/blender/makesrna/intern/rna_rigidbody.c
+++ b/source/blender/makesrna/intern/rna_rigidbody.c
@@ -215,7 +215,7 @@ static void rna_RigidBodyOb_reset(Main *UNUSED(bmain), Scene *scene, PointerRNA
static void rna_RigidBodyOb_shape_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Object *ob = ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
rna_RigidBodyOb_reset(bmain, scene, ptr);
@@ -859,6 +859,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_pointer_sdna(prop, NULL, "group");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Collection", "Collection containing objects participating in this simulation");
RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_objects_collection_update");
@@ -866,6 +867,7 @@ static void rna_def_rigidbody_world(BlenderRNA *brna)
prop = RNA_def_property(srna, "constraints", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Collection");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Constraints", "Collection containing rigid body constraint objects");
RNA_def_property_update(prop, NC_SCENE, "rna_RigidBodyWorld_constraints_collection_update");
@@ -1224,15 +1226,15 @@ static void rna_def_rigidbody_constraint(BlenderRNA *brna)
prop = RNA_def_property(srna, "object1", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob1");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Object 1", "First Rigid Body Object to be constrained");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
prop = RNA_def_property(srna, "object2", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob2");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Object 2", "Second Rigid Body Object to be constrained");
- RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_OBJECT | ND_POINTCACHE, "rna_RigidBodyOb_reset");
/* Breaking Threshold */
diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c
index 631ad72e146..6e21d02c0b3 100644
--- a/source/blender/makesrna/intern/rna_rna.c
+++ b/source/blender/makesrna/intern/rna_rna.c
@@ -388,10 +388,10 @@ void rna_builtin_properties_begin(CollectionPropertyIterator *iter, PointerRNA *
newptr.data = ptr->type;
if (ptr->type->flag & STRUCT_ID) {
- newptr.id.data = ptr->data;
+ newptr.owner_id = ptr->data;
}
else {
- newptr.id.data = NULL;
+ newptr.owner_id = NULL;
}
iter->parent = newptr;
@@ -414,7 +414,7 @@ int rna_builtin_properties_lookup_string(PointerRNA *ptr, const char *key, Point
{
StructRNA *srna;
PropertyRNA *prop;
- PointerRNA propptr = {{NULL}};
+ PointerRNA propptr = {NULL};
srna = ptr->type;
@@ -770,7 +770,8 @@ static void rna_IntProperty_default_array_get(PointerRNA *ptr, int *values)
PropertyRNA *prop = (PropertyRNA *)ptr->data;
rna_idproperty_check(&prop, ptr);
if (prop->totarraylength > 0) {
- RNA_property_int_get_default_array(ptr, prop, values);
+ PointerRNA null_ptr = PointerRNA_NULL;
+ RNA_property_int_get_default_array(&null_ptr, prop, values);
}
}
@@ -779,7 +780,8 @@ static void rna_BoolProperty_default_array_get(PointerRNA *ptr, bool *values)
PropertyRNA *prop = (PropertyRNA *)ptr->data;
rna_idproperty_check(&prop, ptr);
if (prop->totarraylength > 0) {
- RNA_property_boolean_get_default_array(ptr, prop, values);
+ PointerRNA null_ptr = PointerRNA_NULL;
+ RNA_property_boolean_get_default_array(&null_ptr, prop, values);
}
}
@@ -788,7 +790,8 @@ static void rna_FloatProperty_default_array_get(PointerRNA *ptr, float *values)
PropertyRNA *prop = (PropertyRNA *)ptr->data;
rna_idproperty_check(&prop, ptr);
if (prop->totarraylength > 0) {
- RNA_property_float_get_default_array(ptr, prop, values);
+ PointerRNA null_ptr = PointerRNA_NULL;
+ RNA_property_float_get_default_array(&null_ptr, prop, values);
}
}
@@ -1226,7 +1229,7 @@ static bool rna_property_override_diff_propptr_validate_diffing(PointerRNA *prop
}
if (*r_is_id) {
- BLI_assert(propptr_a->data == propptr_a->id.data && propptr_b->data == propptr_b->id.data);
+ BLI_assert(propptr_a->data == propptr_a->owner_id && propptr_b->data == propptr_b->owner_id);
}
return is_valid_for_diffing;
@@ -1241,6 +1244,10 @@ static int rna_property_override_diff_propptr(Main *bmain,
const bool no_prop_name,
IDOverrideLibrary *override,
const char *rna_path,
+ const char *rna_itemname_a,
+ const char *rna_itemname_b,
+ const int rna_itemindex_a,
+ const int rna_itemindex_b,
const int flags,
bool *r_override_changed)
{
@@ -1282,9 +1289,18 @@ static int rna_property_override_diff_propptr(Main *bmain,
IDOverrideLibraryProperty *op = BKE_override_library_property_get(
override, rna_path, &created);
- if (op != NULL && created) { /* If not yet overridden... */
- BKE_override_library_property_operation_get(
- op, IDOVERRIDE_LIBRARY_OP_REPLACE, NULL, NULL, -1, -1, true, NULL, NULL);
+ /* If not yet overridden, or if we are handling sub-items (inside a collection)... */
+ if (op != NULL && (created || rna_itemname_a != NULL || rna_itemname_b != NULL ||
+ rna_itemindex_a != -1 || rna_itemindex_b != -1)) {
+ BKE_override_library_property_operation_get(op,
+ IDOVERRIDE_LIBRARY_OP_REPLACE,
+ rna_itemname_b,
+ rna_itemname_a,
+ rna_itemindex_b,
+ rna_itemindex_a,
+ true,
+ NULL,
+ &created);
if (r_override_changed) {
*r_override_changed = created;
}
@@ -1294,12 +1310,56 @@ static int rna_property_override_diff_propptr(Main *bmain,
return comp;
}
else {
+ /* In case we got some array/collection like items identifiers, now is the time to generate a
+ * proper rna path from those. */
+# define RNA_PATH_BUFFSIZE 8192
+
+ char extended_rna_path_buffer[RNA_PATH_BUFFSIZE];
+ char *extended_rna_path = extended_rna_path_buffer;
+
+# define RNA_PATH_PRINTF(_str, ...) \
+ if (BLI_snprintf(extended_rna_path_buffer, RNA_PATH_BUFFSIZE, (_str), __VA_ARGS__) >= \
+ RNA_PATH_BUFFSIZE - 1) { \
+ extended_rna_path = BLI_sprintfN((_str), __VA_ARGS__); \
+ } \
+ (void)0
+# define RNA_PATH_FREE() \
+ if (extended_rna_path != extended_rna_path_buffer && extended_rna_path != rna_path) \
+ MEM_freeN(extended_rna_path)
+
+ /* There may be a propname defined in some cases, while no actual name set
+ * (e.g. happens with point cache), in that case too we want to fall back to index.
+ * Note that we do not need the RNA path for insertion operations. */
+ if (rna_path) {
+ if ((rna_itemname_a != NULL && rna_itemname_a[0] != '\0') &&
+ (rna_itemname_b != NULL && rna_itemname_b[0] != '\0')) {
+ BLI_assert(STREQ(rna_itemname_a, rna_itemname_b));
+ char esc_item_name[RNA_PATH_BUFFSIZE];
+ BLI_strescape(esc_item_name, rna_itemname_a, RNA_PATH_BUFFSIZE);
+ RNA_PATH_PRINTF("%s[\"%s\"]", rna_path, esc_item_name);
+ }
+ else if (rna_itemindex_a != -1) { /* Based on index... */
+ BLI_assert(rna_itemindex_a == rna_itemindex_b);
+ RNA_PATH_PRINTF("%s[%d]", rna_path, rna_itemindex_a);
+ }
+ else {
+ extended_rna_path = (char *)rna_path;
+ }
+ }
+
eRNAOverrideMatchResult report_flags = 0;
const bool match = RNA_struct_override_matches(
- bmain, propptr_a, propptr_b, rna_path, override, flags, &report_flags);
+ bmain, propptr_a, propptr_b, extended_rna_path, override, flags, &report_flags);
if (r_override_changed && (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) != 0) {
*r_override_changed = true;
}
+
+ RNA_PATH_FREE();
+
+# undef RNA_PATH_BUFFSIZE
+# undef RNA_PATH_PRINTF
+# undef RNA_PATH_FREE
+
return !match;
}
}
@@ -1616,6 +1676,10 @@ int rna_property_override_diff_default(Main *bmain,
no_prop_name,
override,
rna_path,
+ NULL,
+ NULL,
+ -1,
+ -1,
flags,
r_override_changed);
}
@@ -1636,21 +1700,6 @@ int rna_property_override_diff_default(Main *bmain,
int idx_a = 0;
int idx_b = 0;
-# define RNA_PATH_BUFFSIZE 8192
-
- char extended_rna_path_buffer[RNA_PATH_BUFFSIZE];
- char *extended_rna_path = extended_rna_path_buffer;
-
-# define RNA_PATH_PRINTF(_str, ...) \
- if (BLI_snprintf(extended_rna_path_buffer, RNA_PATH_BUFFSIZE, (_str), __VA_ARGS__) >= \
- RNA_PATH_BUFFSIZE - 1) { \
- extended_rna_path = BLI_sprintfN((_str), __VA_ARGS__); \
- } \
- (void)0
-# define RNA_PATH_FREE() \
- if (extended_rna_path != extended_rna_path_buffer) \
- MEM_freeN(extended_rna_path)
-
CollectionPropertyIterator iter_a, iter_b;
RNA_property_collection_begin(ptr_a, prop_a, &iter_a);
RNA_property_collection_begin(ptr_b, prop_b, &iter_b);
@@ -1730,41 +1779,15 @@ int rna_property_override_diff_default(Main *bmain,
# endif
if (!(is_id || is_valid_for_diffing || is_valid_for_insertion)) {
- /* Differences we cannot handle, we can break here
- * (we do not support replacing ID pointers in collections e.g.). */
+ /* Differences we cannot handle, we can break here. */
equals = false;
abort = true;
break;
}
- /* There may be a propname defined in some cases, while no actual name set
- * (e.g. happens with point cache), in that case too we want to fall back to index.
- * Note that we do not need the RNA path for insertion operations. */
- if (is_id || is_valid_for_diffing) {
- if ((propname_a != NULL && propname_a[0] != '\0') &&
- (propname_b != NULL && propname_b[0] != '\0')) {
- if (rna_path) {
- /* In case of name, either it is valid for diffing, and _a and _b are identical,
- * or it is valid for insertion, and we need to use _a. */
- char esc_item_name[RNA_PATH_BUFFSIZE];
- BLI_strescape(esc_item_name, propname_a, RNA_PATH_BUFFSIZE);
- RNA_PATH_PRINTF("%s[\"%s\"]", rna_path, esc_item_name);
- }
- }
- else { /* Based on index... */
- if (rna_path) {
- /* In case of indices, we need _a one for insertion,
- * but _b ones for in-depth diffing.
- * Insertion always happen once all 'replace' operations have been done,
- * otherwise local and reference paths for those would have to be different! */
- RNA_PATH_PRINTF("%s[%d]", rna_path, is_valid_for_insertion ? idx_a : idx_b);
- }
- }
- }
-
- /* Collections do not support replacement of their data
- * (since they do not support removing), only in *some* cases, insertion.
- * We also assume then that _a data is the one where things are inserted. */
+ /* Collections do not support replacement of their data (except for collections of ID
+ * pointers), since they do not support removing, only in *some* cases, insertion. We
+ * also assume then that _a data is the one where things are inserted. */
if (is_valid_for_insertion && use_insertion) {
bool created;
IDOverrideLibraryProperty *op = BKE_override_library_property_get(
@@ -1812,7 +1835,11 @@ int rna_property_override_diff_default(Main *bmain,
no_ownership,
no_prop_name,
override,
- extended_rna_path,
+ rna_path,
+ propname_a,
+ propname_b,
+ idx_a,
+ idx_b,
flags,
r_override_changed);
equals = equals && eq;
@@ -1839,7 +1866,6 @@ int rna_property_override_diff_default(Main *bmain,
propname_b = buff_b;
}
propname_b[0] = '\0';
- RNA_PATH_FREE();
if (!do_create && !equals) {
abort = true; /* Early out in case we do not want to loop over whole collection. */
@@ -1864,10 +1890,6 @@ int rna_property_override_diff_default(Main *bmain,
RNA_property_collection_next(&iter_b);
idx_b++;
}
-
-# undef RNA_PATH_BUFFSIZE
-# undef RNA_PATH_PRINTF
-# undef RNA_PATH_FREE
}
/* Not same number of items in both collections. */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index 4397d204972..3d2d91d2334 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -168,6 +168,16 @@ const EnumPropertyItem rna_enum_snap_element_items[] = {
{SCE_SNAP_MODE_EDGE, "EDGE", ICON_SNAP_EDGE, "Edge", "Snap to edges"},
{SCE_SNAP_MODE_FACE, "FACE", ICON_SNAP_FACE, "Face", "Snap to faces"},
{SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume"},
+ {SCE_SNAP_MODE_EDGE_MIDPOINT,
+ "EDGE_MIDPOINT",
+ ICON_SNAP_MIDPOINT,
+ "Edge Center",
+ "Snap to the middle of edges"},
+ {SCE_SNAP_MODE_EDGE_PERPENDICULAR,
+ "EDGE_PERPENDICULAR",
+ ICON_SNAP_PERPENDICULAR,
+ "Edge Perpendicular",
+ "Snap to the nearest point on an edge"},
{0, NULL, 0, NULL, NULL},
};
@@ -740,6 +750,65 @@ static void rna_GPencilInterpolateSettings_type_set(PointerRNA *ptr, int value)
}
}
+static void rna_Gpencil_selectmode_update(bContext *C, PointerRNA *ptr)
+{
+ ToolSettings *ts = (ToolSettings *)ptr->data;
+ /* If the mode is not Stroke, don't extend selection. */
+ if ((ts->gpencil_selectmode_edit & GP_SELECTMODE_STROKE) == 0) {
+ return;
+ }
+
+ /* Extend selection to all points in all selected strokes. */
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *ob = OBACT(view_layer);
+ if ((ob) && (ob->type == OB_GPENCIL)) {
+ bGPdata *gpd = (bGPdata *)ob->data;
+ CTX_DATA_BEGIN (C, bGPDstroke *, gps, editable_gpencil_strokes) {
+ if ((gps->flag & GP_STROKE_SELECT) && (gps->totpoints > 1)) {
+ bGPDspoint *pt;
+ for (int i = 0; i < gps->totpoints; i++) {
+ pt = &gps->points[i];
+ pt->flag |= GP_SPOINT_SELECT;
+ }
+ }
+ }
+ CTX_DATA_END;
+
+ gpd->flag |= GP_DATA_CACHE_IS_DIRTY;
+ DEG_id_tag_update(&gpd->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY);
+ }
+}
+
+static void rna_Gpencil_mask_point_update(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *ptr)
+{
+ ToolSettings *ts = (ToolSettings *)ptr->data;
+
+ ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_STROKE;
+ ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_SEGMENT;
+}
+
+static void rna_Gpencil_mask_stroke_update(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *ptr)
+{
+ ToolSettings *ts = (ToolSettings *)ptr->data;
+
+ ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_POINT;
+ ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_SEGMENT;
+}
+
+static void rna_Gpencil_mask_segment_update(Main *UNUSED(bmain),
+ Scene *UNUSED(scene),
+ PointerRNA *ptr)
+{
+ ToolSettings *ts = (ToolSettings *)ptr->data;
+
+ ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_POINT;
+ ts->gpencil_selectmode_sculpt &= ~GP_SCULPT_MASK_SELECTMODE_STROKE;
+}
+
/* Read-only Iterator of all the scene objects. */
static void rna_Scene_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
@@ -796,7 +865,7 @@ static void rna_Scene_set_set(PointerRNA *ptr,
void rna_Scene_set_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
DEG_relations_tag_update(bmain);
DEG_id_tag_update_ex(bmain, &scene->id, 0);
@@ -822,8 +891,8 @@ static void rna_Scene_fps_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(p
{
DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_FPS | ID_RECALC_SEQUENCER_STRIPS);
/* NOTE: Tag via dependency graph will take care of all the updates ion the evaluated domain,
- * however, changes in FPS actually modifies an original stip length, so this we take care about
- * here. */
+ * however, changes in FPS actually modifies an original skip length,
+ * so this we take care about here. */
BKE_sequencer_refresh_sound_length(bmain, scene);
}
@@ -834,7 +903,7 @@ static void rna_Scene_listener_update(Main *UNUSED(bmain), Scene *scene, Pointer
static void rna_Scene_volume_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_VOLUME | ID_RECALC_SEQUENCER_STRIPS);
}
@@ -958,7 +1027,7 @@ static void rna_Scene_show_subframe_update(Main *UNUSED(bmain),
Scene *UNUSED(current_scene),
PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
scene->r.subframe = 0.0f;
}
@@ -966,7 +1035,7 @@ static void rna_Scene_frame_update(Main *UNUSED(bmain),
Scene *UNUSED(current_scene),
PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_SEEK);
WM_main_add_notifier(NC_SCENE | ND_FRAME, scene);
}
@@ -1079,7 +1148,7 @@ static char *rna_BakeSettings_path(PointerRNA *UNUSED(ptr))
static char *rna_ImageFormatSettings_path(PointerRNA *ptr)
{
ImageFormatData *imf = (ImageFormatData *)ptr->data;
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
switch (GS(id->name)) {
case ID_SCE: {
@@ -1150,7 +1219,7 @@ static bool rna_RenderSettings_is_movie_format_get(PointerRNA *ptr)
static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value)
{
ImageFormatData *imf = (ImageFormatData *)ptr->data;
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
imf->imtype = value;
const bool is_render = (id && GS(id->name) == ID_SCE);
@@ -1191,7 +1260,7 @@ static void rna_ImageFormatSettings_file_format_set(PointerRNA *ptr, int value)
}
if (id && GS(id->name) == ID_SCE) {
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
RenderData *rd = &scene->r;
# ifdef WITH_FFMPEG
BKE_ffmpeg_image_type_verify(rd, imf);
@@ -1205,7 +1274,7 @@ static const EnumPropertyItem *rna_ImageFormatSettings_file_format_itemf(bContex
PropertyRNA *UNUSED(prop),
bool *UNUSED(r_free))
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (id && GS(id->name) == ID_SCE) {
return rna_enum_image_type_items;
}
@@ -1220,7 +1289,7 @@ static const EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext
bool *r_free)
{
ImageFormatData *imf = (ImageFormatData *)ptr->data;
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
const bool is_render = (id && GS(id->name) == ID_SCE);
/* note, we need to act differently for render
@@ -1236,7 +1305,7 @@ static const EnumPropertyItem *rna_ImageFormatSettings_color_mode_itemf(bContext
* the same MPEG format with QTRLE codec can easily handle alpha channel.
* not sure how to deal with such cases in a nicer way (sergey) */
if (is_render) {
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
RenderData *rd = &scene->r;
if (BKE_ffmpeg_alpha_channel_is_supported(rd)) {
@@ -1405,7 +1474,7 @@ static void rna_SceneRender_file_ext_get(PointerRNA *ptr, char *str)
# ifdef WITH_FFMPEG
static void rna_FFmpegSettings_lossless_output_set(PointerRNA *ptr, bool value)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
RenderData *rd = &scene->r;
if (value) {
@@ -1422,7 +1491,7 @@ static void rna_FFmpegSettings_codec_settings_update(Main *UNUSED(bmain),
Scene *UNUSED(scene_unused),
PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
RenderData *rd = &scene->r;
BKE_ffmpeg_codec_settings_verify(rd);
@@ -1521,7 +1590,7 @@ static void rna_RenderSettings_engine_set(PointerRNA *ptr, int value)
if (type) {
BLI_strncpy_utf8(rd->engine, type->idname, sizeof(rd->engine));
- DEG_id_tag_update(ptr->id.data, ID_RECALC_COPY_ON_WRITE);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_COPY_ON_WRITE);
}
}
@@ -1577,20 +1646,20 @@ static bool rna_RenderSettings_multiple_engines_get(PointerRNA *UNUSED(ptr))
static bool rna_RenderSettings_use_spherical_stereo_get(PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
return BKE_scene_use_spherical_stereo(scene);
}
void rna_Scene_glsl_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
DEG_id_tag_update(&scene->id, 0);
}
static void rna_Scene_world_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Scene *sc = (Scene *)ptr->id.data;
+ Scene *sc = (Scene *)ptr->owner_id;
rna_Scene_glsl_update(bmain, scene, ptr);
WM_main_add_notifier(NC_WORLD | ND_WORLD, &sc->id);
@@ -1599,7 +1668,7 @@ static void rna_Scene_world_update(Main *bmain, Scene *scene, PointerRNA *ptr)
void rna_Scene_freestyle_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
DEG_id_tag_update(&scene->id, 0);
}
@@ -1615,7 +1684,7 @@ void rna_Scene_use_view_map_cache_update(Main *UNUSED(bmain),
void rna_ViewLayer_name_set(PointerRNA *ptr, const char *value)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
ViewLayer *view_layer = (ViewLayer *)ptr->data;
BLI_assert(BKE_id_is_in_global_main(&scene->id));
BKE_view_layer_rename(G_MAIN, scene, view_layer, value);
@@ -1623,7 +1692,7 @@ void rna_ViewLayer_name_set(PointerRNA *ptr, const char *value)
static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
SceneRenderView *rv = (SceneRenderView *)ptr->data;
BLI_strncpy_utf8(rv->name, value, sizeof(rv->name));
BLI_uniquename(&scene->r.views,
@@ -1636,14 +1705,14 @@ static void rna_SceneRenderView_name_set(PointerRNA *ptr, const char *value)
void rna_ViewLayer_material_override_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
rna_Scene_glsl_update(bmain, scene, ptr);
DEG_relations_tag_update(bmain);
}
void rna_ViewLayer_pass_update(Main *bmain, Scene *activescene, PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
if (scene->nodetree) {
ntreeCompositUpdateRLayers(scene->nodetree);
@@ -1676,7 +1745,7 @@ static void rna_Physics_relations_update(Main *bmain,
static void rna_Physics_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
FOREACH_SCENE_OBJECT_BEGIN (scene, ob) {
BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
}
@@ -1763,7 +1832,7 @@ static void object_simplify_update(Object *ob)
static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *sce = ptr->id.data;
+ Scene *sce = (Scene *)ptr->owner_id;
Scene *sce_iter;
Base *base;
@@ -1784,7 +1853,7 @@ static void rna_Scene_use_simplify_update(Main *bmain, Scene *UNUSED(scene), Poi
static void rna_Scene_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- Scene *sce = ptr->id.data;
+ Scene *sce = (Scene *)ptr->owner_id;
if (sce->r.mode & R_SIMPLIFY) {
rna_Scene_use_simplify_update(bmain, scene, ptr);
@@ -1795,7 +1864,7 @@ static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- Scene *sce = ptr->id.data;
+ Scene *sce = (Scene *)ptr->owner_id;
if (!(sce->r.mode & R_PERSISTENT_DATA)) {
RE_FreePersistentData();
@@ -1806,7 +1875,7 @@ static void rna_Scene_use_persistent_data_update(Main *UNUSED(bmain),
static void rna_Scene_transform_orientation_slots_begin(CollectionPropertyIterator *iter,
PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
TransformOrientationSlot *orient_slot = &scene->orientation_slots[0];
rna_iterator_array_begin(
iter, orient_slot, sizeof(*orient_slot), ARRAY_SIZE(scene->orientation_slots), 0, NULL);
@@ -1814,7 +1883,7 @@ static void rna_Scene_transform_orientation_slots_begin(CollectionPropertyIterat
static int rna_Scene_transform_orientation_slots_length(PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
return ARRAY_SIZE(scene->orientation_slots);
}
@@ -2062,7 +2131,7 @@ static void rna_Scene_update_active_object_data(bContext *C, PointerRNA *UNUSED(
static void rna_SceneCamera_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Object *camera = scene->camera;
BKE_sequence_invalidate_scene_strips(bmain, scene);
@@ -2203,7 +2272,7 @@ void rna_FreestyleSettings_module_remove(ID *id,
static void rna_Stereo3dFormat_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (id && GS(id->name) == ID_IM) {
Image *ima = (Image *)id;
@@ -2251,7 +2320,7 @@ static void rna_ViewLayer_remove(
static int rna_TransformOrientationSlot_type_get(PointerRNA *ptr)
{
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
TransformOrientationSlot *orient_slot = ptr->data;
if (orient_slot != &scene->orientation_slots[SCE_ORIENT_DEFAULT]) {
if ((orient_slot->flag & SELECT) == 0) {
@@ -2263,7 +2332,7 @@ static int rna_TransformOrientationSlot_type_get(PointerRNA *ptr)
void rna_TransformOrientationSlot_type_set(PointerRNA *ptr, int value)
{
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
TransformOrientationSlot *orient_slot = ptr->data;
if (orient_slot != &scene->orientation_slots[SCE_ORIENT_DEFAULT]) {
@@ -2281,7 +2350,7 @@ void rna_TransformOrientationSlot_type_set(PointerRNA *ptr, int value)
static PointerRNA rna_TransformOrientationSlot_get(PointerRNA *ptr)
{
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
TransformOrientationSlot *orient_slot = ptr->data;
TransformOrientation *orientation;
if (orient_slot->type < V3D_ORIENT_CUSTOM) {
@@ -2339,8 +2408,8 @@ const EnumPropertyItem *rna_TransformOrientation_itemf(bContext *C,
bool *r_free)
{
Scene *scene;
- if (ptr->id.data && (GS(((ID *)ptr->id.data)->name) == ID_SCE)) {
- scene = ptr->id.data;
+ if (ptr->owner_id && (GS(ptr->owner_id->name) == ID_SCE)) {
+ scene = (Scene *)ptr->owner_id;
}
else {
scene = CTX_data_scene(C);
@@ -2353,7 +2422,7 @@ const EnumPropertyItem *rna_TransformOrientation_with_scene_itemf(bContext *UNUS
PropertyRNA *UNUSED(prop),
bool *r_free)
{
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
TransformOrientationSlot *orient_slot = ptr->data;
bool include_default = (orient_slot != &scene->orientation_slots[SCE_ORIENT_DEFAULT]);
return rna_TransformOrientation_impl_itemf(scene, include_default, r_free);
@@ -2954,14 +3023,29 @@ static void rna_def_tool_settings(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_transform_pivot_point_align", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "transform_flag", SCE_XFORM_AXIS_ALIGN);
RNA_def_property_ui_text(
- prop, "Only Origins", "Manipulate origins (object, pose and weight paint mode only)");
- RNA_def_property_ui_icon(prop, ICON_CENTER_ONLY, 0);
- RNA_def_property_update(prop, NC_SCENE, NULL);
+ prop, "Only Locations", "Manipulate origins (object, pose and weight paint mode only)");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "use_transform_data_origin", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "transform_flag", SCE_XFORM_DATA_ORIGIN);
+ RNA_def_property_ui_text(prop, "Data Origins", "Manipulate object data");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ prop = RNA_def_property(srna, "use_transform_skip_children", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "transform_flag", SCE_XFORM_SKIP_CHILDREN);
+ RNA_def_property_ui_text(prop, "Skip Children", "Don't transform children");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "use_mesh_automerge", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "automerge", 0);
+ RNA_def_property_boolean_sdna(prop, NULL, "automerge", AUTO_MERGE);
RNA_def_property_ui_text(
- prop, "Auto Merge", "Automatically merge vertices moved to the same location");
+ prop, "Auto Merge Vertices", "Automatically merge vertices moved to the same location");
+ RNA_def_property_ui_icon(prop, ICON_AUTOMERGE_OFF, 1);
+ RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
+
+ prop = RNA_def_property(srna, "use_mesh_automerge_and_split", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "automerge", AUTO_MERGE_AND_SPLIT);
+ RNA_def_property_ui_text(prop, "Split Edges & Faces", "Automatically split edges and faces");
RNA_def_property_ui_icon(prop, ICON_AUTOMERGE_OFF, 1);
RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */
@@ -3117,12 +3201,40 @@ static void rna_def_tool_settings(BlenderRNA *brna)
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 - Select mode */
- prop = RNA_def_property(srna, "gpencil_selectmode", PROP_ENUM, PROP_NONE);
- RNA_def_property_enum_sdna(prop, NULL, "gpencil_selectmode");
+ /* Grease Pencil - Select mode Edit */
+ prop = RNA_def_property(srna, "gpencil_selectmode_edit", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "gpencil_selectmode_edit");
RNA_def_property_enum_items(prop, gpencil_selectmode_items);
RNA_def_property_ui_text(prop, "Select Mode", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Gpencil_selectmode_update");
+
+ /* Grease Pencil - Select mode Sculpt */
+ prop = RNA_def_property(srna, "use_gpencil_select_mask_point", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(
+ prop, NULL, "gpencil_selectmode_sculpt", GP_SCULPT_MASK_SELECTMODE_POINT);
+ RNA_def_property_ui_text(prop, "Selection Mask", "Only sculpt selected stroke points");
+ RNA_def_property_ui_icon(prop, ICON_GP_SELECT_POINTS, 0);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Gpencil_mask_point_update");
+
+ prop = RNA_def_property(srna, "use_gpencil_select_mask_stroke", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(
+ prop, NULL, "gpencil_selectmode_sculpt", GP_SCULPT_MASK_SELECTMODE_STROKE);
+ RNA_def_property_ui_text(prop, "Selection Mask", "Only sculpt selected stroke");
+ RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Gpencil_mask_stroke_update");
+
+ prop = RNA_def_property(srna, "use_gpencil_select_mask_segment", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(
+ prop, NULL, "gpencil_selectmode_sculpt", GP_SCULPT_MASK_SELECTMODE_SEGMENT);
+ RNA_def_property_ui_text(
+ prop, "Selection Mask", "Only sculpt selected stroke points between other strokes");
+ RNA_def_property_ui_icon(prop, ICON_GP_SELECT_BETWEEN_STROKES, 0);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Gpencil_mask_segment_update");
/* Annotations - 2D Views Stroke Placement */
prop = RNA_def_property(srna, "annotation_stroke_placement_view2d", PROP_ENUM, PROP_NONE);
@@ -3708,6 +3820,7 @@ void rna_def_view_layer_common(StructRNA *srna, const bool scene)
RNA_def_property_pointer_sdna(prop, NULL, "mat_override");
RNA_def_property_struct_type(prop, "Material");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(
prop, "Material Override", "Material to override all other materials in this view layer");
RNA_def_property_update(
@@ -5019,7 +5132,7 @@ static void rna_def_image_format_stereo3d_format(BlenderRNA *brna)
/* use for render output and image save operator,
* note: there are some cases where the members act differently when this is
* used from a scene, video formats can only be selected for render output
- * for example, this is checked by seeing if the ptr->id.data is a Scene id */
+ * for example, this is checked by seeing if the ptr->owner_id is a Scene id */
static void rna_def_scene_image_format_data(BlenderRNA *brna)
{
@@ -7477,6 +7590,7 @@ void RNA_def_scene(BlenderRNA *brna)
/* Global Settings */
prop = RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Camera_object_poll");
RNA_def_property_ui_text(prop, "Camera", "Active camera, used for rendering the scene");
RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_camera_update");
@@ -7485,12 +7599,14 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "set");
RNA_def_property_struct_type(prop, "Scene");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_pointer_funcs(prop, NULL, "rna_Scene_set_set", NULL, NULL);
RNA_def_property_ui_text(prop, "Background Scene", "Background set scene");
RNA_def_property_update(prop, NC_SCENE | NA_EDITED, "rna_Scene_set_update");
prop = RNA_def_property(srna, "world", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "World", "World used for rendering the scene");
RNA_def_property_update(prop, NC_SCENE | ND_WORLD, "rna_Scene_world_update");
@@ -7851,6 +7967,7 @@ void RNA_def_scene(BlenderRNA *brna)
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_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
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);
diff --git a/source/blender/makesrna/intern/rna_screen.c b/source/blender/makesrna/intern/rna_screen.c
index c868c79e968..728ef3fb706 100644
--- a/source/blender/makesrna/intern/rna_screen.c
+++ b/source/blender/makesrna/intern/rna_screen.c
@@ -149,7 +149,7 @@ static void rna_Area_type_set(PointerRNA *ptr, int value)
static void rna_Area_type_update(bContext *C, PointerRNA *ptr)
{
- bScreen *sc = (bScreen *)ptr->id.data;
+ bScreen *sc = (bScreen *)ptr->owner_id;
ScrArea *sa = (ScrArea *)ptr->data;
/* Running update without having called 'set', see: T64049 */
diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c
index 84f2cb7c1be..2e3f41d656b 100644
--- a/source/blender/makesrna/intern/rna_sculpt_paint.c
+++ b/source/blender/makesrna/intern/rna_sculpt_paint.c
@@ -319,7 +319,7 @@ static char *rna_ParticleEdit_path(PointerRNA *UNUSED(ptr))
static bool rna_Brush_mode_poll(PointerRNA *ptr, PointerRNA value)
{
const Paint *paint = ptr->data;
- Brush *brush = value.id.data;
+ Brush *brush = (Brush *)value.owner_id;
const uint tool_offset = paint->runtime.tool_offset;
const eObjectMode ob_mode = paint->runtime.ob_mode;
UNUSED_VARS_NDEBUG(tool_offset);
@@ -350,10 +350,10 @@ static bool paint_contains_brush_slot(const Paint *paint, const PaintToolSlot *t
static bool rna_Brush_mode_with_tool_poll(PointerRNA *ptr, PointerRNA value)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
const PaintToolSlot *tslot = ptr->data;
ToolSettings *ts = scene->toolsettings;
- Brush *brush = value.id.data;
+ Brush *brush = (Brush *)value.owner_id;
int mode = 0;
int slot_index = 0;
@@ -438,7 +438,7 @@ static char *rna_Sculpt_path(PointerRNA *UNUSED(ptr))
static char *rna_VertexPaint_path(PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
ToolSettings *ts = scene->toolsettings;
if (ptr->data == ts->vpaint) {
return BLI_strdup("tool_settings.vertex_paint");
@@ -1420,13 +1420,6 @@ static void rna_def_gpencil_sculpt(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Guide", "");
- prop = RNA_def_property(srna, "use_select_mask", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SCULPT_SETT_FLAG_SELECT_MASK);
- RNA_def_property_ui_text(prop, "Selection Mask", "Only sculpt selected stroke points");
- RNA_def_property_ui_icon(prop, ICON_GP_ONLY_SELECTED, 0);
- RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
- RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL);
-
prop = RNA_def_property(srna, "use_edit_position", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_SCULPT_SETT_FLAG_APPLY_POSITION);
RNA_def_property_ui_text(prop, "Affect Position", "The brush affects the position of the point");
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 80a4defba00..efb2fd376b3 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -100,7 +100,7 @@ static void meta_tmp_ref(Sequence *seq_par, Sequence *seq)
static void rna_SequenceElement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
if (ed) {
@@ -119,7 +119,7 @@ static void rna_Sequence_invalidate_raw_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
if (ed) {
@@ -133,7 +133,7 @@ static void rna_Sequence_invalidate_preprocessed_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
if (ed) {
@@ -147,7 +147,7 @@ static void rna_Sequence_invalidate_composite_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
if (ed) {
@@ -179,7 +179,7 @@ static void rna_Sequence_use_sequence(Main *bmain, Scene *scene, PointerRNA *ptr
static void rna_SequenceEditor_sequences_all_begin(CollectionPropertyIterator *iter,
PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
meta_tmp_ref(NULL, ed->seqbase.first);
@@ -281,7 +281,7 @@ static void do_sequence_frame_change_update(Scene *scene, Sequence *seq)
*/
static void rna_Sequence_frame_change_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
do_sequence_frame_change_update(scene, (Sequence *)ptr->data);
rna_Sequence_invalidate_preprocessed_update(bmain, scene, ptr);
}
@@ -289,7 +289,7 @@ static void rna_Sequence_frame_change_update(Main *bmain, Scene *UNUSED(scene),
static void rna_Sequence_start_frame_set(PointerRNA *ptr, int value)
{
Sequence *seq = (Sequence *)ptr->data;
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
BKE_sequence_translate(scene, seq, value - seq->start);
do_sequence_frame_change_update(scene, seq);
@@ -298,7 +298,7 @@ static void rna_Sequence_start_frame_set(PointerRNA *ptr, int value)
static void rna_Sequence_start_frame_final_set(PointerRNA *ptr, int value)
{
Sequence *seq = (Sequence *)ptr->data;
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
BKE_sequence_tx_set_final_left(seq, value);
BKE_sequence_single_fix(seq);
@@ -308,7 +308,7 @@ static void rna_Sequence_start_frame_final_set(PointerRNA *ptr, int value)
static void rna_Sequence_end_frame_final_set(PointerRNA *ptr, int value)
{
Sequence *seq = (Sequence *)ptr->data;
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
BKE_sequence_tx_set_final_right(seq, value);
BKE_sequence_single_fix(seq);
@@ -318,7 +318,7 @@ static void rna_Sequence_end_frame_final_set(PointerRNA *ptr, int value)
static void rna_Sequence_anim_startofs_final_set(PointerRNA *ptr, int value)
{
Sequence *seq = (Sequence *)ptr->data;
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
seq->anim_startofs = MIN2(value, seq->len + seq->anim_startofs);
@@ -329,7 +329,7 @@ static void rna_Sequence_anim_startofs_final_set(PointerRNA *ptr, int value)
static void rna_Sequence_anim_endofs_final_set(PointerRNA *ptr, int value)
{
Sequence *seq = (Sequence *)ptr->data;
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
seq->anim_endofs = MIN2(value, seq->len + seq->anim_endofs);
@@ -340,7 +340,7 @@ static void rna_Sequence_anim_endofs_final_set(PointerRNA *ptr, int value)
static void rna_Sequence_frame_length_set(PointerRNA *ptr, int value)
{
Sequence *seq = (Sequence *)ptr->data;
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
BKE_sequence_tx_set_final_right(seq, BKE_sequence_tx_get_final_left(seq, false) + value);
do_sequence_frame_change_update(scene, seq);
@@ -362,7 +362,7 @@ static int rna_Sequence_frame_editable(PointerRNA *ptr, const char **UNUSED(r_in
static void rna_Sequence_channel_set(PointerRNA *ptr, int value)
{
Sequence *seq = (Sequence *)ptr->data;
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
ListBase *seqbase = BKE_sequence_seqbase(&ed->seqbase, seq);
@@ -445,7 +445,7 @@ static Sequence *sequence_get_by_transform(Editing *ed, StripTransform *transfor
static char *rna_SequenceTransform_path(PointerRNA *ptr)
{
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_transform(ed, ptr->data);
@@ -464,7 +464,7 @@ static void rna_SequenceTransform_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_transform(ed, ptr->data);
@@ -497,7 +497,7 @@ static Sequence *sequence_get_by_crop(Editing *ed, StripCrop *crop)
static char *rna_SequenceCrop_path(PointerRNA *ptr)
{
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_crop(ed, ptr->data);
@@ -514,7 +514,7 @@ static char *rna_SequenceCrop_path(PointerRNA *ptr)
static void rna_SequenceCrop_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_crop(ed, ptr->data);
@@ -551,7 +551,7 @@ static int rna_Sequence_name_length(PointerRNA *ptr)
static void rna_Sequence_name_set(PointerRNA *ptr, const char *value)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Sequence *seq = (Sequence *)ptr->data;
char oldname[sizeof(seq->name)];
AnimData *adt;
@@ -782,7 +782,7 @@ static void rna_SequenceElement_filename_set(PointerRNA *ptr, const char *value)
static void rna_Sequence_reopen_files_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
BKE_sequencer_free_imbuf(scene, &ed->seqbase, false);
@@ -795,14 +795,14 @@ static void rna_Sequence_reopen_files_update(Main *bmain, Scene *UNUSED(scene),
static void rna_Sequence_mute_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
DEG_id_tag_update(&scene->id, ID_RECALC_SEQUENCER_STRIPS);
}
static void rna_Sequence_filepath_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Sequence *seq = (Sequence *)(ptr->data);
BKE_sequence_reload_new_file(bmain, scene, seq, true);
BKE_sequence_calc(scene, seq);
@@ -838,7 +838,7 @@ static Sequence *sequence_get_by_proxy(Editing *ed, StripProxy *proxy)
static void rna_Sequence_tcindex_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_proxy(ed, ptr->data);
@@ -848,7 +848,7 @@ static void rna_Sequence_tcindex_update(Main *bmain, Scene *UNUSED(scene), Point
static void rna_SequenceProxy_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_proxy(ed, ptr->data);
@@ -911,7 +911,7 @@ static Sequence *sequence_get_by_colorbalance(Editing *ed,
static char *rna_SequenceColorBalance_path(PointerRNA *ptr)
{
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
SequenceModifierData *smd;
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_colorbalance(ed, ptr->data, &smd);
@@ -944,7 +944,7 @@ static void rna_SequenceColorBalance_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
SequenceModifierData *smd;
Sequence *seq = sequence_get_by_colorbalance(ed, ptr->data, &smd);
@@ -954,7 +954,7 @@ static void rna_SequenceColorBalance_update(Main *UNUSED(bmain),
static void rna_SequenceEditor_overlay_lock_set(PointerRNA *ptr, bool value)
{
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
if (ed == NULL) {
@@ -974,7 +974,7 @@ static void rna_SequenceEditor_overlay_lock_set(PointerRNA *ptr, bool value)
static int rna_SequenceEditor_overlay_frame_get(PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
if (ed == NULL) {
@@ -991,7 +991,7 @@ static int rna_SequenceEditor_overlay_frame_get(PointerRNA *ptr)
static void rna_SequenceEditor_overlay_frame_set(PointerRNA *ptr, int value)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
if (ed == NULL) {
@@ -1055,7 +1055,7 @@ static StructRNA *rna_SequenceModifier_refine(struct PointerRNA *ptr)
static char *rna_SequenceModifier_path(PointerRNA *ptr)
{
- Scene *scene = ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
SequenceModifierData *smd = ptr->data;
Sequence *seq = sequence_get_by_modifier(ed, smd);
@@ -1077,7 +1077,7 @@ static char *rna_SequenceModifier_path(PointerRNA *ptr)
static void rna_SequenceModifier_name_set(PointerRNA *ptr, const char *value)
{
SequenceModifierData *smd = ptr->data;
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_modifier(ed, smd);
AnimData *adt;
@@ -1106,7 +1106,7 @@ static void rna_SequenceModifier_name_set(PointerRNA *ptr, const char *value)
static void rna_SequenceModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
/* strip from other scenes could be modified, so using active scene is not reliable */
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_modifier(ed, ptr->data);
@@ -1115,7 +1115,7 @@ static void rna_SequenceModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene
static bool rna_SequenceModifier_otherSequence_poll(PointerRNA *ptr, PointerRNA value)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Editing *ed = BKE_sequencer_editing_get(scene, false);
Sequence *seq = sequence_get_by_modifier(ed, ptr->data);
Sequence *cur = (Sequence *)value.data;
@@ -1181,7 +1181,7 @@ static void rna_Sequence_modifier_clear(Sequence *seq, bContext *C)
static float rna_Sequence_fps_get(PointerRNA *ptr)
{
- Scene *scene = (Scene *)ptr->id.data;
+ Scene *scene = (Scene *)ptr->owner_id;
Sequence *seq = (Sequence *)(ptr->data);
return BKE_sequence_get_fps(scene, seq);
}
@@ -1457,7 +1457,7 @@ static const EnumPropertyItem blend_mode_items[] = {
{0, "", ICON_NONE, NULL, NULL},
{SEQ_TYPE_DARKEN, "DARKEN", 0, "Darken", ""},
{SEQ_TYPE_MUL, "MULTIPLY", 0, "Multiply", ""},
- {SEQ_TYPE_BURN, "BURN", 0, "Burn", ""},
+ {SEQ_TYPE_COLOR_BURN, "BURN", 0, "Color Burn", ""},
{SEQ_TYPE_LINEAR_BURN, "LINEAR_BURN", 0, "Linear Burn", ""},
{0, "", ICON_NONE, NULL, NULL},
{SEQ_TYPE_LIGHTEN, "LIGHTEN", 0, "Lighten", ""},
@@ -2758,14 +2758,16 @@ static void rna_def_text(StructRNA *srna)
prop = RNA_def_property(srna, "align_x", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align");
RNA_def_property_enum_items(prop, text_align_x_items);
- RNA_def_property_ui_text(prop, "Align X", "Align the text along the X axis");
+ RNA_def_property_ui_text(
+ prop, "Align X", "Align the text along the X axis, relative to the text midpoint");
RNA_def_property_update(
prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
prop = RNA_def_property(srna, "align_y", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "align_y");
RNA_def_property_enum_items(prop, text_align_y_items);
- RNA_def_property_ui_text(prop, "Align Y", "Align the image along the Y axis");
+ RNA_def_property_ui_text(
+ prop, "Align Y", "Align the image along the Y axis, relative to the text midpoint");
RNA_def_property_update(
prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update");
@@ -2792,7 +2794,7 @@ static void rna_def_color_mix(StructRNA *srna)
{SEQ_TYPE_SCREEN, "SCREEN", 0, "Screen", ""},
{SEQ_TYPE_OVERLAY, "OVERLAY", 0, "Overlay", ""},
{SEQ_TYPE_DODGE, "DODGE", 0, "Dodge", ""},
- {SEQ_TYPE_BURN, "BURN", 0, "Burn", ""},
+ {SEQ_TYPE_COLOR_BURN, "BURN", 0, "Color Burn", ""},
{SEQ_TYPE_LINEAR_BURN, "LINEAR_BURN", 0, "Linear Burn", ""},
{SEQ_TYPE_SOFT_LIGHT, "SOFT_LIGHT", 0, "Soft Light", ""},
{SEQ_TYPE_HARD_LIGHT, "HARD_LIGHT", 0, "Hard Light", ""},
diff --git a/source/blender/makesrna/intern/rna_shader_fx.c b/source/blender/makesrna/intern/rna_shader_fx.c
index e48e682018d..acf525e1788 100644
--- a/source/blender/makesrna/intern/rna_shader_fx.c
+++ b/source/blender/makesrna/intern/rna_shader_fx.c
@@ -140,8 +140,8 @@ static void rna_ShaderFx_name_set(PointerRNA *ptr, const char *value)
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;
+ if (ptr->owner_id) {
+ Object *ob = (Object *)ptr->owner_id;
BKE_shaderfx_unique_name(&ob->shader_fx, gmd);
}
@@ -160,8 +160,8 @@ static char *rna_ShaderFx_path(PointerRNA *ptr)
static void rna_ShaderFx_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
- WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->id.data);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
+ WM_main_add_notifier(NC_OBJECT | ND_MODIFIER, ptr->owner_id);
}
static void rna_ShaderFx_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -189,7 +189,7 @@ static void shaderfx_object_set(Object *self, Object **ob_p, int type, PointerRN
PointerRNA *ptr, PointerRNA value, struct ReportList *UNUSED(reports)) \
{ \
_type##ShaderFxData *tmd = (_type##ShaderFxData *)ptr->data; \
- shaderfx_object_set(ptr->id.data, &tmd->_prop, _obtype, value); \
+ shaderfx_object_set((Object *)ptr->owner_id, &tmd->_prop, _obtype, value); \
}
RNA_FX_OBJECT_SET(Light, object, OB_EMPTY);
@@ -212,7 +212,7 @@ static void rna_def_shader_fx_blur(BlenderRNA *brna)
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_range(prop, 0, SHRT_MAX);
RNA_def_property_ui_text(prop, "Factor", "Factor of Blur");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
@@ -329,7 +329,7 @@ static void rna_def_shader_fx_pixel(BlenderRNA *brna)
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_range(prop, 1, SHRT_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");
@@ -359,7 +359,7 @@ static void rna_def_shader_fx_rim(BlenderRNA *brna)
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_range(prop, SHRT_MIN, SHRT_MAX);
RNA_def_property_ui_text(prop, "Offset", "Offset of the rim");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
@@ -385,7 +385,7 @@ static void rna_def_shader_fx_rim(BlenderRNA *brna)
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_range(prop, 0, SHRT_MAX);
RNA_def_property_ui_text(
prop, "Blur", "Number of pixels for blurring rim (set to 0 to disable)");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
@@ -418,11 +418,12 @@ static void rna_def_shader_fx_shadow(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Object", "Object to determine center of rotation");
RNA_def_property_pointer_funcs(prop, NULL, "rna_ShadowShaderFx_object_set", NULL, NULL);
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_ShaderFx_dependency_update");
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_range(prop, SHRT_MIN, SHRT_MAX);
RNA_def_property_ui_text(prop, "Offset", "Offset of the shadow");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
@@ -472,7 +473,7 @@ static void rna_def_shader_fx_shadow(BlenderRNA *brna)
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_range(prop, 0, SHRT_MAX);
RNA_def_property_ui_text(
prop, "Blur", "Number of pixels for blurring shadow (set to 0 to disable)");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
@@ -537,7 +538,7 @@ static void rna_def_shader_fx_glow(BlenderRNA *brna)
* but only makes public first array element. */
prop = RNA_def_property(srna, "radius", PROP_INT, PROP_PIXEL);
RNA_def_property_int_sdna(prop, NULL, "blur[0]");
- RNA_def_property_range(prop, 0, INT_MAX);
+ RNA_def_property_range(prop, 0, SHRT_MAX);
RNA_def_property_ui_text(
prop, "Radius", "Number of pixels for blurring glow (set to 0 to disable)");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
@@ -568,7 +569,7 @@ static void rna_def_shader_fx_swirl(BlenderRNA *brna)
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_range(prop, 0, SHRT_MAX);
RNA_def_property_ui_text(prop, "Radius", "Radius to apply");
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_ShaderFx_update");
@@ -588,6 +589,7 @@ static void rna_def_shader_fx_swirl(BlenderRNA *brna)
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_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_ShaderFx_dependency_update");
}
@@ -640,6 +642,7 @@ static void rna_def_shader_fx_light(BlenderRNA *brna)
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_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_ShaderFx_dependency_update");
}
diff --git a/source/blender/makesrna/intern/rna_smoke.c b/source/blender/makesrna/intern/rna_smoke.c
index 5c04802ac3c..fa0297ac306 100644
--- a/source/blender/makesrna/intern/rna_smoke.c
+++ b/source/blender/makesrna/intern/rna_smoke.c
@@ -55,7 +55,7 @@
static void rna_Smoke_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
}
static void rna_Smoke_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr)
@@ -70,13 +70,13 @@ static void rna_Smoke_resetCache(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin
if (settings->smd && settings->smd->domain) {
settings->point_cache[0]->flag |= PTCACHE_OUTDATED;
}
- DEG_id_tag_update(ptr->id.data, ID_RECALC_GEOMETRY);
+ DEG_id_tag_update(ptr->owner_id, ID_RECALC_GEOMETRY);
}
static void rna_Smoke_cachetype_set(struct PointerRNA *ptr, int value)
{
SmokeDomainSettings *settings = (SmokeDomainSettings *)ptr->data;
- Object *ob = (Object *)ptr->id.data;
+ Object *ob = (Object *)ptr->owner_id;
if (value != settings->cache_file_format) {
/* Clear old caches. */
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index 8108311319b..d866e1a98be 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -422,19 +422,19 @@ const EnumPropertyItem rna_enum_file_sort_items[] = {
{FILE_SORT_ALPHA,
"FILE_SORT_ALPHA",
ICON_SORTALPHA,
- "Sort alphabetically",
+ "Name",
"Sort the file list alphabetically"},
{FILE_SORT_EXTENSION,
"FILE_SORT_EXTENSION",
ICON_SORTBYEXT,
- "Sort by extension",
+ "Extension",
"Sort the file list by extension/type"},
{FILE_SORT_TIME,
"FILE_SORT_TIME",
ICON_SORTTIME,
- "Sort by time",
+ "Modified Date",
"Sort files by modification time"},
- {FILE_SORT_SIZE, "FILE_SORT_SIZE", ICON_SORTSIZE, "Sort by size", "Sort files by size"},
+ {FILE_SORT_SIZE, "FILE_SORT_SIZE", ICON_SORTSIZE, "Size", "Sort files by size"},
{0, NULL, 0, NULL, NULL},
};
@@ -524,7 +524,7 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr)
static ScrArea *rna_area_from_space(PointerRNA *ptr)
{
- bScreen *sc = (bScreen *)ptr->id.data;
+ bScreen *sc = (bScreen *)ptr->owner_id;
SpaceLink *link = (SpaceLink *)ptr->data;
return BKE_screen_find_area_from_space(sc, link);
}
@@ -553,7 +553,7 @@ static void area_region_from_regiondata(bScreen *sc,
static void rna_area_region_from_regiondata(PointerRNA *ptr, ScrArea **r_sa, ARegion **r_ar)
{
- bScreen *sc = (bScreen *)ptr->id.data;
+ bScreen *sc = (bScreen *)ptr->owner_id;
void *regiondata = ptr->data;
area_region_from_regiondata(sc, regiondata, r_sa, r_ar);
@@ -771,7 +771,7 @@ static void rna_Space_view2d_sync_update(Main *UNUSED(bmain),
ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
if (ar) {
- bScreen *sc = (bScreen *)ptr->id.data;
+ bScreen *sc = (bScreen *)ptr->owner_id;
View2D *v2d = &ar->v2d;
UI_view2d_sync(sc, sa, v2d, V2D_LOCK_SET);
@@ -804,7 +804,7 @@ static void rna_SpaceView3D_camera_update(Main *bmain, Scene *scene, PointerRNA
static void rna_SpaceView3D_use_local_camera_set(PointerRNA *ptr, bool value)
{
View3D *v3d = (View3D *)(ptr->data);
- bScreen *sc = (bScreen *)ptr->id.data;
+ bScreen *sc = (bScreen *)ptr->owner_id;
v3d->scenelock = !value;
@@ -817,7 +817,7 @@ static void rna_SpaceView3D_use_local_camera_set(PointerRNA *ptr, bool value)
static float rna_View3DOverlay_GridScaleUnit_get(PointerRNA *ptr)
{
View3D *v3d = (View3D *)(ptr->data);
- bScreen *screen = ptr->id.data;
+ bScreen *screen = (bScreen *)ptr->owner_id;
Scene *scene = ED_screen_scene_find(screen, G_MAIN->wm.first);
return ED_view3d_grid_scale(scene, v3d, NULL);
@@ -934,7 +934,7 @@ static bool rna_RegionView3D_is_orthographic_side_view_get(PointerRNA *ptr)
static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (GS(id->name) == ID_SCE) {
return;
}
@@ -951,7 +951,7 @@ static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA
}
}
- bScreen *screen = ptr->id.data;
+ bScreen *screen = (bScreen *)ptr->owner_id;
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) {
@@ -968,12 +968,12 @@ static void rna_3DViewShading_type_update(Main *bmain, Scene *scene, PointerRNA
static Scene *rna_3DViewShading_scene(PointerRNA *ptr)
{
/* Get scene, depends if using 3D view or OpenGL render settings. */
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (GS(id->name) == ID_SCE) {
return (Scene *)id;
}
else {
- bScreen *screen = ptr->id.data;
+ bScreen *screen = (bScreen *)ptr->owner_id;
return WM_windows_scene_get_from_screen(G_MAIN->wm.first, screen);
}
}
@@ -1296,7 +1296,7 @@ static bool rna_SpaceImageEditor_show_paint_get(PointerRNA *ptr)
static bool rna_SpaceImageEditor_show_uvedit_get(PointerRNA *ptr)
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
- bScreen *sc = (bScreen *)ptr->id.data;
+ bScreen *sc = (bScreen *)ptr->owner_id;
wmWindow *win = ED_screen_window_find(sc, G_MAIN->wm.first);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
@@ -1306,7 +1306,7 @@ static bool rna_SpaceImageEditor_show_uvedit_get(PointerRNA *ptr)
static bool rna_SpaceImageEditor_show_maskedit_get(PointerRNA *ptr)
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
- bScreen *sc = (bScreen *)ptr->id.data;
+ bScreen *sc = (bScreen *)ptr->owner_id;
wmWindow *win = ED_screen_window_find(sc, G_MAIN->wm.first);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
return ED_space_image_check_show_maskedit(sima, view_layer);
@@ -1317,7 +1317,7 @@ static void rna_SpaceImageEditor_image_set(PointerRNA *ptr,
struct ReportList *UNUSED(reports))
{
SpaceImage *sima = (SpaceImage *)(ptr->data);
- bScreen *sc = (bScreen *)ptr->id.data;
+ bScreen *sc = (bScreen *)ptr->owner_id;
wmWindow *win = ED_screen_window_find(sc, G_MAIN->wm.first);
ViewLayer *view_layer = WM_window_get_active_view_layer(win);
Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
@@ -2106,7 +2106,7 @@ static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr,
struct ReportList *UNUSED(reports))
{
SpaceClip *sc = (SpaceClip *)(ptr->data);
- bScreen *screen = (bScreen *)ptr->id.data;
+ bScreen *screen = (bScreen *)ptr->owner_id;
ED_space_clip_set_clip(NULL, screen, sc, (MovieClip *)value.data);
}
@@ -2156,6 +2156,18 @@ static void rna_SpaceClipEditor_view_type_update(Main *UNUSED(bmain),
/* File browser. */
+int rna_FileSelectParams_filename_editable(struct PointerRNA *ptr, const char **r_info)
+{
+ FileSelectParams *params = ptr->data;
+
+ if (params && (params->flag & FILE_DIRSEL_ONLY)) {
+ *r_info = "Only directories can be chosen for the current operation.";
+ return 0;
+ }
+
+ return params ? PROP_EDITABLE : 0;
+}
+
static bool rna_FileSelectParams_use_lib_get(PointerRNA *ptr)
{
FileSelectParams *params = ptr->data;
@@ -2725,11 +2737,6 @@ static void rna_def_space_image_uv(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Display Faces", "Display faces over the image");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
- prop = RNA_def_property(srna, "show_edges", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SI_NO_DRAWEDGES);
- RNA_def_property_ui_text(prop, "Display Edges", "Display edges in vertex select mode");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL);
-
/* todo: move edge and face drawing options here from G.f */
prop = RNA_def_property(srna, "pixel_snap_mode", PROP_ENUM, PROP_NONE);
@@ -2791,6 +2798,7 @@ static void rna_def_space_outliner(BlenderRNA *brna)
static const EnumPropertyItem filter_state_items[] = {
{SO_FILTER_OB_ALL, "ALL", 0, "All", "Show all objects in the view layer"},
{SO_FILTER_OB_VISIBLE, "VISIBLE", 0, "Visible", "Show visible objects"},
+ {SO_FILTER_OB_HIDDEN, "HIDDEN", 0, "Hidden", "Show hidden objects"},
{SO_FILTER_OB_SELECTED, "SELECTED", 0, "Selected", "Show selected objects"},
{SO_FILTER_OB_ACTIVE, "ACTIVE", 0, "Active", "Show only the active object"},
{0, NULL, 0, NULL, NULL},
@@ -2829,6 +2837,12 @@ static void rna_def_space_outliner(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Sort Alphabetically", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+ prop = RNA_def_property(srna, "use_sync_select", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SO_SYNC_SELECT);
+ RNA_def_property_ui_text(
+ prop, "Sync Outliner Selection", "Sync outliner selection with other editors");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_OUTLINER, NULL);
+
/* Granular restriction column option. */
prop = RNA_def_property(srna, "show_restrict_column_enable", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "show_restrict_flags", SO_RESTRICT_ENABLE);
@@ -3788,7 +3802,7 @@ static void rna_def_space_view3d(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_gizmo_navigate", PROP_BOOLEAN, PROP_NONE);
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_ui_text(prop, "Navigate Gizmo", "Viewport navigation gizmo");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
prop = RNA_def_property(srna, "show_gizmo_context", PROP_BOOLEAN, PROP_NONE);
@@ -4440,13 +4454,6 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
/* flags */
- prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SEQ_NO_DRAW_CFRANUM);
- RNA_def_property_ui_text(prop,
- "Show Frame Number Indicator",
- "Show frame number beside the current frame indicator line");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
-
prop = RNA_def_property(srna, "show_frames", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_DRAWFRAMES);
RNA_def_property_ui_text(prop, "Display Frames", "Display frames rather than seconds");
@@ -4734,13 +4741,6 @@ static void rna_def_space_dopesheet(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_DOPESHEET, NULL);
- prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SACTION_NODRAWCFRANUM);
- RNA_def_property_ui_text(prop,
- "Show Frame Number Indicator",
- "Show frame number beside the current frame indicator line");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_DOPESHEET, NULL);
-
prop = RNA_def_property(srna, "show_sliders", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SACTION_SLIDERS);
RNA_def_property_ui_text(prop, "Show Sliders", "Show sliders beside F-Curve channels");
@@ -4896,13 +4896,6 @@ static void rna_def_space_graph(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_GRAPH, NULL);
- prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SIPO_NODRAWCFRANUM);
- RNA_def_property_ui_text(prop,
- "Show Frame Number Indicator",
- "Show frame number beside the current frame indicator line");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_GRAPH, NULL);
-
prop = RNA_def_property(srna, "show_sliders", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIPO_SLIDERS);
RNA_def_property_ui_text(prop, "Show Sliders", "Show sliders beside F-Curve channels");
@@ -5040,13 +5033,6 @@ static void rna_def_space_nla(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_NLA, NULL);
- prop = RNA_def_property(srna, "show_frame_indicator", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NODRAWCFRANUM);
- RNA_def_property_ui_text(prop,
- "Show Frame Number Indicator",
- "Show frame number beside the current frame indicator line");
- RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL);
-
prop = RNA_def_property(srna, "show_strip_curves", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NOSTRIPCURVES);
RNA_def_property_ui_text(prop, "Show Control F-Curves", "Show influence F-Curves on strips");
@@ -5173,25 +5159,25 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
PropertyRNA *prop;
static const EnumPropertyItem file_display_items[] = {
- {FILE_SHORTDISPLAY,
- "LIST_SHORT",
- ICON_SHORTDISPLAY,
- "Short List",
- "Display files as short list"},
- {FILE_LONGDISPLAY,
- "LIST_LONG",
+ {FILE_VERTICALDISPLAY,
+ "LIST_VERTICAL",
ICON_LONGDISPLAY,
- "Long List",
- "Display files as a detailed list"},
+ "Vertical List",
+ "Display files as a vertical list"},
+ {FILE_HORIZONTALDISPLAY,
+ "LIST_HORIZONTAL",
+ ICON_SHORTDISPLAY,
+ "Horizontal List",
+ "Display files as a horizontal list"},
{FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"},
{0, NULL, 0, NULL, NULL},
};
static const EnumPropertyItem display_size_items[] = {
- {32, "TINY", 0, "Tiny", ""},
- {64, "SMALL", 0, "Small", ""},
+ {64, "TINY", 0, "Tiny", ""},
+ {96, "SMALL", 0, "Small", ""},
{128, "NORMAL", 0, "Regular", ""},
- {256, "LARGE", 0, "Large", ""},
+ {192, "LARGE", 0, "Large", ""},
{0, NULL, 0, NULL, NULL},
};
@@ -5307,7 +5293,10 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Title", "Title for the file browser");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
- prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH);
+ /* Use BYTESTRING rather than DIRPATH as subtype so UI code doesn't add OT_directory_browse
+ * button when displaying this prop in the file browser (it would just open a file browser). That
+ * should be the only effective difference between the two. */
+ prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_BYTESTRING);
RNA_def_property_string_sdna(prop, NULL, "dir");
RNA_def_property_ui_text(prop, "Directory", "Directory displayed in the file browser");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
@@ -5315,6 +5304,7 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
prop = RNA_def_property(srna, "filename", PROP_STRING, PROP_FILENAME);
RNA_def_property_string_sdna(prop, NULL, "file");
RNA_def_property_ui_text(prop, "File Name", "Active file in the file browser");
+ RNA_def_property_editable_func(prop, "rna_FileSelectParams_filename_editable");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
prop = RNA_def_property(srna, "use_library_browsing", PROP_BOOLEAN, PROP_NONE);
@@ -5335,6 +5325,19 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Recursion", "Numbers of dirtree levels to show simultaneously");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ prop = RNA_def_property(srna, "show_details_size", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "details_flags", FILE_DETAILS_SIZE);
+ RNA_def_property_ui_text(prop, "File Size", "Draw a column listing the size of each file");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+
+ prop = RNA_def_property(srna, "show_details_datetime", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "details_flags", FILE_DETAILS_DATETIME);
+ RNA_def_property_ui_text(
+ prop,
+ "File Modification Date",
+ "Draw a column listing the date and time of modification for each file");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+
prop = RNA_def_property(srna, "use_filter", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_FILTER);
RNA_def_property_ui_text(prop, "Filter Files", "Enable filtering of files");
@@ -5351,6 +5354,12 @@ static void rna_def_fileselect_params(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Sort", "");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+ prop = RNA_def_property(srna, "use_sort_invert", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", FILE_SORT_INVERT);
+ RNA_def_property_ui_text(
+ prop, "Reverse Sorting", "Sort items descending, from highest value to lowest");
+ RNA_def_property_update(prop, NC_SPACE | ND_SPACE_FILE_PARAMS, NULL);
+
prop = RNA_def_property(srna, "use_filter_image", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "filter", FILE_TYPE_IMAGE);
RNA_def_property_ui_text(prop, "Filter Images", "Show image files");
diff --git a/source/blender/makesrna/intern/rna_speaker.c b/source/blender/makesrna/intern/rna_speaker.c
index 0c63cf5eae8..8f156a67e08 100644
--- a/source/blender/makesrna/intern/rna_speaker.c
+++ b/source/blender/makesrna/intern/rna_speaker.c
@@ -61,6 +61,7 @@ static void rna_def_speaker(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Sound");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Sound", "Sound data-block used by this speaker");
/* RNA_def_property_float_funcs(prop, NULL, "rna_Speaker_sound_set", NULL); */
/* RNA_def_property_update(prop, 0, "rna_Speaker_update"); */
diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c
index 28d2d722460..2015356d071 100644
--- a/source/blender/makesrna/intern/rna_texture.c
+++ b/source/blender/makesrna/intern/rna_texture.c
@@ -186,10 +186,10 @@ static StructRNA *rna_Texture_refine(struct PointerRNA *ptr)
static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (GS(id->name) == ID_TE) {
- Tex *tex = ptr->id.data;
+ Tex *tex = (Tex *)ptr->owner_id;
DEG_id_tag_update(&tex->id, 0);
DEG_id_tag_update(&tex->id, ID_RECALC_EDITORS);
@@ -197,7 +197,7 @@ static void rna_Texture_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *pt
WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, NULL);
}
else if (GS(id->name) == ID_NT) {
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
ED_node_tag_update_nodetree(bmain, ntree, NULL);
}
}
@@ -219,7 +219,7 @@ static void rna_Color_mapping_update(Main *UNUSED(bmain),
/* Used for Texture Properties, used (also) for/in Nodes */
static void rna_Texture_nodes_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- Tex *tex = ptr->id.data;
+ Tex *tex = (Tex *)ptr->owner_id;
DEG_id_tag_update(&tex->id, 0);
DEG_id_tag_update(&tex->id, ID_RECALC_EDITORS);
@@ -235,7 +235,7 @@ static void rna_Texture_type_set(PointerRNA *ptr, int value)
void rna_TextureSlot_update(bContext *C, PointerRNA *ptr)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
DEG_id_tag_update(id, 0);
@@ -290,8 +290,8 @@ char *rna_TextureSlot_path(PointerRNA *ptr)
* since the name used is the name of the texture assigned, but the texture
* may be used multiple times in the same stack
*/
- if (ptr->id.data) {
- if (GS(((ID *)ptr->id.data)->name) == ID_BR) {
+ if (ptr->owner_id) {
+ if (GS(ptr->owner_id->name) == ID_BR) {
return BLI_strdup("texture_slot");
}
else {
@@ -299,7 +299,7 @@ char *rna_TextureSlot_path(PointerRNA *ptr)
PropertyRNA *prop;
/* find the 'textures' property of the ID-struct */
- RNA_id_pointer_create(ptr->id.data, &id_ptr);
+ RNA_id_pointer_create(ptr->owner_id, &id_ptr);
prop = RNA_struct_find_property(&id_ptr, "texture_slots");
/* get an iterator for this property, and try to find the relevant index */
@@ -630,6 +630,7 @@ static void rna_def_mtex(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "tex");
RNA_def_property_struct_type(prop, "Texture");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_CONTEXT_UPDATE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Texture", "Texture data-block used by this texture slot");
RNA_def_property_update(prop, NC_MATERIAL | ND_SHADING_LINKS, "rna_TextureSlot_update");
@@ -834,7 +835,7 @@ static void rna_def_texture_clouds(BlenderRNA *brna)
prop = RNA_def_property(srna, "noise_depth", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "noisedepth");
RNA_def_property_range(prop, 0, 30);
- RNA_def_property_ui_range(prop, 0, 24, 0, 2);
+ RNA_def_property_ui_range(prop, 0, 24, 1, 2);
RNA_def_property_ui_text(prop, "Noise Depth", "Depth of the cloud calculation");
RNA_def_property_update(prop, 0, "rna_Texture_nodes_update");
@@ -973,7 +974,7 @@ static void rna_def_texture_marble(BlenderRNA *brna)
prop = RNA_def_property(srna, "noise_depth", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "noisedepth");
RNA_def_property_range(prop, 0, 30);
- RNA_def_property_ui_range(prop, 0, 24, 0, 2);
+ RNA_def_property_ui_range(prop, 0, 24, 1, 2);
RNA_def_property_ui_text(prop, "Noise Depth", "Depth of the cloud calculation");
RNA_def_property_update(prop, 0, "rna_Texture_update");
@@ -1027,7 +1028,7 @@ static void rna_def_texture_magic(BlenderRNA *brna)
prop = RNA_def_property(srna, "noise_depth", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "noisedepth");
RNA_def_property_range(prop, 0, 30);
- RNA_def_property_ui_range(prop, 0, 24, 0, 2);
+ RNA_def_property_ui_range(prop, 0, 24, 1, 2);
RNA_def_property_ui_text(prop, "Noise Depth", "Depth of the noise");
RNA_def_property_update(prop, 0, "rna_Texture_update");
}
@@ -1277,6 +1278,7 @@ static void rna_def_texture_image(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "ima");
RNA_def_property_struct_type(prop, "Image");
RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Image", "");
RNA_def_property_update(prop, 0, "rna_Texture_update");
diff --git a/source/blender/makesrna/intern/rna_timeline.c b/source/blender/makesrna/intern/rna_timeline.c
index 3308a493212..ed17a509fc2 100644
--- a/source/blender/makesrna/intern/rna_timeline.c
+++ b/source/blender/makesrna/intern/rna_timeline.c
@@ -70,6 +70,7 @@ static void rna_def_timeline_marker(BlenderRNA *brna)
prop = RNA_def_property(srna, "camera", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Camera", "Camera that becomes active on this frame");
# endif
}
diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c
index 84bde91e654..0a824b3c67a 100644
--- a/source/blender/makesrna/intern/rna_tracking.c
+++ b/source/blender/makesrna/intern/rna_tracking.c
@@ -61,7 +61,7 @@ static void rna_tracking_defaultSettings_patternUpdate(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTracking *tracking = &clip->tracking;
MovieTrackingSettings *settings = &tracking->settings;
@@ -74,7 +74,7 @@ static void rna_tracking_defaultSettings_searchUpdate(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTracking *tracking = &clip->tracking;
MovieTrackingSettings *settings = &tracking->settings;
@@ -85,7 +85,7 @@ static void rna_tracking_defaultSettings_searchUpdate(Main *UNUSED(bmain),
static char *rna_trackingTrack_path(PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data;
/* Escaped object name, escaped track name, rest of the path. */
char rna_path[MAX_NAME * 4 + 64];
@@ -95,35 +95,35 @@ static char *rna_trackingTrack_path(PointerRNA *ptr)
static void rna_trackingTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
rna_iterator_listbase_begin(iter, &clip->tracking.tracks, NULL);
}
static void rna_trackingPlaneTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
rna_iterator_listbase_begin(iter, &clip->tracking.plane_tracks, NULL);
}
static void rna_trackingObjects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
rna_iterator_listbase_begin(iter, &clip->tracking.objects, NULL);
}
static int rna_tracking_active_object_index_get(PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
return clip->tracking.objectnr;
}
static void rna_tracking_active_object_index_set(PointerRNA *ptr, int value)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
clip->tracking.objectnr = value;
BKE_tracking_dopesheet_tag_update(&clip->tracking);
@@ -132,7 +132,7 @@ static void rna_tracking_active_object_index_set(PointerRNA *ptr, int value)
static void rna_tracking_active_object_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
*min = 0;
*max = max_ii(0, clip->tracking.tot_object - 1);
@@ -140,7 +140,7 @@ static void rna_tracking_active_object_index_range(
static PointerRNA rna_tracking_active_track_get(PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingTrack *act_track = BKE_tracking_track_get_active(&clip->tracking);
return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingTrack, act_track);
@@ -150,7 +150,7 @@ static void rna_tracking_active_track_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingTrack *track = (MovieTrackingTrack *)value.data;
ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking);
int index = BLI_findindex(tracksbase, track);
@@ -165,7 +165,7 @@ static void rna_tracking_active_track_set(PointerRNA *ptr,
static PointerRNA rna_tracking_active_plane_track_get(PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingPlaneTrack *act_plane_track = BKE_tracking_plane_track_get_active(&clip->tracking);
return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingPlaneTrack, act_plane_track);
@@ -175,7 +175,7 @@ static void rna_tracking_active_plane_track_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)value.data;
ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking);
int index = BLI_findindex(plane_tracks_base, plane_track);
@@ -190,7 +190,7 @@ static void rna_tracking_active_plane_track_set(PointerRNA *ptr,
static void rna_trackingTrack_name_set(PointerRNA *ptr, const char *value)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingTrack *track = (MovieTrackingTrack *)ptr->data;
ListBase *tracksbase = BKE_tracking_find_tracks_list_for_track(&clip->tracking, track);
/* Store old name, for the animation fix later. */
@@ -233,7 +233,7 @@ static void rna_trackingTrack_select_set(PointerRNA *ptr, bool value)
static void rna_trackingPlaneMarker_frame_set(PointerRNA *ptr, int value)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTracking *tracking = &clip->tracking;
MovieTrackingPlaneMarker *plane_marker = (MovieTrackingPlaneMarker *)ptr->data;
MovieTrackingObject *tracking_object;
@@ -268,7 +268,7 @@ static void rna_trackingPlaneMarker_frame_set(PointerRNA *ptr, int value)
static char *rna_trackingPlaneTrack_path(PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data;
/* Escaped object name, escaped track name, rest of the path. */
char rna_path[MAX_NAME * 4 + 64];
@@ -279,7 +279,7 @@ static char *rna_trackingPlaneTrack_path(PointerRNA *ptr)
static void rna_trackingPlaneTrack_name_set(PointerRNA *ptr, const char *value)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingPlaneTrack *plane_track = (MovieTrackingPlaneTrack *)ptr->data;
ListBase *plane_tracks_base = BKE_tracking_find_tracks_list_for_plane_track(&clip->tracking,
plane_track);
@@ -307,7 +307,7 @@ static char *rna_trackingCamera_path(PointerRNA *UNUSED(ptr))
static float rna_trackingCamera_focal_mm_get(PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingCamera *camera = &clip->tracking.camera;
float val = camera->focal;
@@ -320,7 +320,7 @@ static float rna_trackingCamera_focal_mm_get(PointerRNA *ptr)
static void rna_trackingCamera_focal_mm_set(PointerRNA *ptr, float value)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingCamera *camera = &clip->tracking.camera;
if (clip->lastsize[0]) {
@@ -362,26 +362,26 @@ static int rna_track_2d_stabilization_rotation(CollectionPropertyIterator *UNUSE
static void rna_tracking_stabTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
rna_iterator_listbase_begin(iter, &clip->tracking.tracks, rna_track_2d_stabilization);
}
static int rna_tracking_stabTracks_active_index_get(PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
return clip->tracking.stabilization.act_track;
}
static void rna_tracking_stabTracks_active_index_set(PointerRNA *ptr, int value)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
clip->tracking.stabilization.act_track = value;
}
static void rna_tracking_stabTracks_active_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
*min = 0;
*max = max_ii(0, clip->tracking.stabilization.tot_track - 1);
@@ -389,26 +389,26 @@ static void rna_tracking_stabTracks_active_index_range(
static void rna_tracking_stabRotTracks_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
rna_iterator_listbase_begin(iter, &clip->tracking.tracks, rna_track_2d_stabilization_rotation);
}
static int rna_tracking_stabRotTracks_active_index_get(PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
return clip->tracking.stabilization.act_rot_track;
}
static void rna_tracking_stabRotTracks_active_index_set(PointerRNA *ptr, int value)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
clip->tracking.stabilization.act_rot_track = value;
}
static void rna_tracking_stabRotTracks_active_index_range(
PointerRNA *ptr, int *min, int *max, int *UNUSED(softmin), int *UNUSED(softmax))
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
*min = 0;
*max = max_ii(0, clip->tracking.stabilization.tot_rot_track - 1);
@@ -416,7 +416,7 @@ static void rna_tracking_stabRotTracks_active_index_range(
static void rna_tracking_flushUpdate(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
nodeUpdateID(scene->nodetree, &clip->id);
@@ -429,7 +429,7 @@ static void rna_tracking_resetIntrinsics(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTracking *tracking = &clip->tracking;
if (tracking->camera.intrinsics) {
@@ -443,7 +443,7 @@ static void rna_trackingObject_tracks_begin(CollectionPropertyIterator *iter, Po
MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
if (object->flag & TRACKING_OBJECT_CAMERA) {
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
rna_iterator_listbase_begin(iter, &clip->tracking.tracks, NULL);
}
@@ -458,7 +458,7 @@ static void rna_trackingObject_plane_tracks_begin(CollectionPropertyIterator *it
MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
if (object->flag & TRACKING_OBJECT_CAMERA) {
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
rna_iterator_listbase_begin(iter, &clip->tracking.plane_tracks, NULL);
}
@@ -472,7 +472,7 @@ static PointerRNA rna_trackingObject_reconstruction_get(PointerRNA *ptr)
MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
if (object->flag & TRACKING_OBJECT_CAMERA) {
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
return rna_pointer_inherit_refine(
ptr, &RNA_MovieTrackingReconstruction, &clip->tracking.reconstruction);
@@ -485,7 +485,7 @@ static PointerRNA rna_trackingObject_reconstruction_get(PointerRNA *ptr)
static PointerRNA rna_tracking_active_object_get(PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingObject *object = BLI_findlink(&clip->tracking.objects, clip->tracking.objectnr);
return rna_pointer_inherit_refine(ptr, &RNA_MovieTrackingObject, object);
@@ -495,7 +495,7 @@ static void rna_tracking_active_object_set(PointerRNA *ptr,
PointerRNA value,
struct ReportList *UNUSED(reports))
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingObject *object = (MovieTrackingObject *)value.data;
int index = BLI_findindex(&clip->tracking.objects, object);
@@ -509,7 +509,7 @@ static void rna_tracking_active_object_set(PointerRNA *ptr,
static void rna_trackingObject_name_set(PointerRNA *ptr, const char *value)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingObject *object = (MovieTrackingObject *)ptr->data;
BLI_strncpy(object->name, value, sizeof(object->name));
@@ -521,7 +521,7 @@ static void rna_trackingObject_flushUpdate(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, NULL);
DEG_id_tag_update(&clip->id, 0);
@@ -529,7 +529,7 @@ static void rna_trackingObject_flushUpdate(Main *UNUSED(bmain),
static void rna_trackingMarker_frame_set(PointerRNA *ptr, int value)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTracking *tracking = &clip->tracking;
MovieTrackingMarker *marker = (MovieTrackingMarker *)ptr->data;
MovieTrackingObject *tracking_object;
@@ -594,7 +594,7 @@ static void rna_trackingDopesheet_tagUpdate(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- MovieClip *clip = (MovieClip *)ptr->id.data;
+ MovieClip *clip = (MovieClip *)ptr->owner_id;
MovieTrackingDopesheet *dopesheet = &clip->tracking.dopesheet;
dopesheet->ok = 0;
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index 097e62a1fea..a7f0c8ff19c 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -1410,7 +1410,7 @@ static void rna_def_panel(BlenderRNA *brna)
prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PNL_PIN);
- RNA_def_property_ui_text(prop, "Pin", "");
+ RNA_def_property_ui_text(prop, "Pin", "Show the panel on all tabs");
/* XXX, should only tag region for redraw */
RNA_def_property_update(prop, NC_WINDOW, NULL);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index a449ed850e9..64ed284eb1f 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -912,6 +912,13 @@ static bool rna_UserDef_studiolight_is_user_defined_get(PointerRNA *ptr)
return (sl->flag & STUDIOLIGHT_USER_DEFINED) != 0;
}
+/* StudioLight.is_user_defined */
+static bool rna_UserDef_studiolight_has_specular_highlight_pass_get(PointerRNA *ptr)
+{
+ StudioLight *sl = (StudioLight *)ptr->data;
+ return sl->flag & STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS;
+}
+
/* StudioLight.type */
static int rna_UserDef_studiolight_type_get(PointerRNA *ptr)
@@ -2297,6 +2304,11 @@ static void rna_def_userdef_theme_space_outliner(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Selected Highlight", "");
RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+ prop = RNA_def_property(srna, "active", PROP_FLOAT, PROP_COLOR_GAMMA);
+ RNA_def_property_array(prop, 3);
+ RNA_def_property_ui_text(prop, "Active Highlight", "");
+ RNA_def_property_update(prop, 0, "rna_userdef_theme_update");
+
prop = RNA_def_property(srna, "selected_object", PROP_FLOAT, PROP_COLOR_GAMMA);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(prop, "Selected Objects", "");
@@ -3695,6 +3707,15 @@ static void rna_def_userdef_studiolight(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "User Defined", "");
+ prop = RNA_def_property(srna, "has_specular_highlight_pass", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(
+ prop, "rna_UserDef_studiolight_has_specular_highlight_pass_get", NULL);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(
+ prop,
+ "Has Specular Highlight",
+ "Studio light image file has separate \"diffuse\" and \"specular\" passes");
+
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, rna_enum_studio_light_type_items);
RNA_def_property_enum_funcs(prop, "rna_UserDef_studiolight_type_get", NULL, NULL);
@@ -4090,6 +4111,12 @@ static void rna_def_userdef_view(BlenderRNA *brna)
"Show the frames per second screen refresh rate, while animation is played back");
RNA_def_property_update(prop, 0, "rna_userdef_update");
+ prop = RNA_def_property(srna, "show_addons_enabled_only", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", USER_ADDONS_ENABLED_ONLY);
+ RNA_def_property_ui_text(prop,
+ "Enabled Add-ons Only",
+ "Only show enabled add-ons. Un-check to see all installed add-ons");
+
static const EnumPropertyItem factor_display_items[] = {
{USER_FACTOR_AS_FACTOR, "FACTOR", 0, "Factor", "Display factors as values between 0 and 1"},
{USER_FACTOR_AS_PERCENTAGE, "PERCENTAGE", 0, "Percentage", "Display factors as percentages"},
diff --git a/source/blender/makesrna/intern/rna_vfont.c b/source/blender/makesrna/intern/rna_vfont.c
index cf61fe07c68..3e96b5816e5 100644
--- a/source/blender/makesrna/intern/rna_vfont.c
+++ b/source/blender/makesrna/intern/rna_vfont.c
@@ -40,7 +40,7 @@
/* matching fnction in rna_ID.c */
static int rna_VectorFont_filepath_editable(PointerRNA *ptr, const char **UNUSED(r_info))
{
- VFont *vfont = ptr->id.data;
+ VFont *vfont = (VFont *)ptr->owner_id;
if (BKE_vfont_is_builtin(vfont)) {
return 0;
}
@@ -51,7 +51,7 @@ static void rna_VectorFont_reload_update(Main *UNUSED(bmain),
Scene *UNUSED(scene),
PointerRNA *ptr)
{
- VFont *vf = ptr->id.data;
+ VFont *vf = (VFont *)ptr->owner_id;
BKE_vfont_free_data(vf);
/* update */
diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c
index 123ec9634c9..c3ffeaf6f6f 100644
--- a/source/blender/makesrna/intern/rna_wm.c
+++ b/source/blender/makesrna/intern/rna_wm.c
@@ -530,7 +530,7 @@ const EnumPropertyItem rna_enum_wm_report_items[] = {
static wmOperator *rna_OperatorProperties_find_operator(PointerRNA *ptr)
{
- wmWindowManager *wm = ptr->id.data;
+ wmWindowManager *wm = (wmWindowManager *)ptr->owner_id;
if (wm) {
IDProperty *properties = (IDProperty *)ptr->data;
@@ -668,7 +668,7 @@ static PointerRNA rna_PopupMenu_layout_get(PointerRNA *ptr)
uiLayout *layout = UI_popup_menu_layout(pup);
PointerRNA rptr;
- RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_UILayout, layout, &rptr);
return rptr;
}
@@ -679,7 +679,7 @@ static PointerRNA rna_PopoverMenu_layout_get(PointerRNA *ptr)
uiLayout *layout = UI_popover_layout(pup);
PointerRNA rptr;
- RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_UILayout, layout, &rptr);
return rptr;
}
@@ -690,7 +690,7 @@ static PointerRNA rna_PieMenu_layout_get(PointerRNA *ptr)
uiLayout *layout = UI_pie_menu_layout(pie);
PointerRNA rptr;
- RNA_pointer_create(ptr->id.data, &RNA_UILayout, layout, &rptr);
+ RNA_pointer_create(ptr->owner_id, &RNA_UILayout, layout, &rptr);
return rptr;
}
@@ -804,7 +804,7 @@ static void rna_Window_screen_set(PointerRNA *ptr,
static bool rna_Window_screen_assign_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
- bScreen *screen = value.id.data;
+ bScreen *screen = (bScreen *)value.owner_id;
return !screen->temp;
}
diff --git a/source/blender/makesrna/intern/rna_wm_gizmo.c b/source/blender/makesrna/intern/rna_wm_gizmo.c
index 534e3042768..ba26929d808 100644
--- a/source/blender/makesrna/intern/rna_wm_gizmo.c
+++ b/source/blender/makesrna/intern/rna_wm_gizmo.c
@@ -252,7 +252,7 @@ static void rna_Gizmo_update_redraw(Main *UNUSED(bmain), Scene *UNUSED(scene), P
static wmGizmo *rna_GizmoProperties_find_operator(PointerRNA *ptr)
{
# if 0
- wmWindowManager *wm = ptr->id.data;
+ wmWindowManager *wm = (wmWindowManager *)ptr->owner_id;
# endif
/* We could try workaruond this lookup, but not trivial. */
diff --git a/source/blender/makesrna/intern/rna_workspace.c b/source/blender/makesrna/intern/rna_workspace.c
index 6349b5206d6..47138653af1 100644
--- a/source/blender/makesrna/intern/rna_workspace.c
+++ b/source/blender/makesrna/intern/rna_workspace.c
@@ -58,7 +58,7 @@ static void rna_window_update_all(Main *UNUSED(bmain),
void rna_workspace_screens_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
- WorkSpace *workspace = ptr->id.data;
+ WorkSpace *workspace = (WorkSpace *)ptr->owner_id;
rna_iterator_listbase_begin(iter, BKE_workspace_layouts_get(workspace), NULL);
}
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index 9b5611f30d7..07db2755523 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -48,17 +48,17 @@
static PointerRNA rna_World_lighting_get(PointerRNA *ptr)
{
- return rna_pointer_inherit_refine(ptr, &RNA_WorldLighting, ptr->id.data);
+ return rna_pointer_inherit_refine(ptr, &RNA_WorldLighting, ptr->owner_id);
}
static PointerRNA rna_World_mist_get(PointerRNA *ptr)
{
- return rna_pointer_inherit_refine(ptr, &RNA_WorldMistSettings, ptr->id.data);
+ return rna_pointer_inherit_refine(ptr, &RNA_WorldMistSettings, ptr->owner_id);
}
static void rna_World_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- World *wo = ptr->id.data;
+ World *wo = (World *)ptr->owner_id;
DEG_id_tag_update(&wo->id, 0);
WM_main_add_notifier(NC_WORLD | ND_WORLD, wo);
@@ -67,7 +67,7 @@ static void rna_World_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR
# if 0
static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- World *wo = ptr->id.data;
+ World *wo = (World *)ptr->owner_id;
DEG_id_tag_update(&wo->id, 0);
WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, wo);
@@ -76,7 +76,7 @@ static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poi
static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
- World *wo = ptr->id.data;
+ World *wo = (World *)ptr->owner_id;
DEG_id_tag_update(&wo->id, 0);
WM_main_add_notifier(NC_WORLD | ND_WORLD_DRAW, wo);
diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index 3d8f96d1abc..8ff66de18b0 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -143,6 +143,10 @@ if(WITH_MOD_OCEANSIM)
add_definitions(-DWITH_OCEANSIM)
endif()
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+endif()
+
if(WITH_BULLET)
list(APPEND LIB
extern_bullet
diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c
index 7ae5fda7111..9f3802a4fa1 100644
--- a/source/blender/modifiers/intern/MOD_armature.c
+++ b/source/blender/modifiers/intern/MOD_armature.c
@@ -82,7 +82,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
/* The object type check is only needed here in case we have a placeholder
* object assigned (because the library containing the armature is missing).
*
- * In other cases it should be impossible.
+ * In other cases it should be impossible to have a type mismatch.
*/
return !amd->object || amd->object->type != OB_ARMATURE;
}
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index fd6f58a21d4..9e368d2c050 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -395,7 +395,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
count = amd->count;
Object *start_cap_ob = amd->start_cap;
- if (start_cap_ob && start_cap_ob != ctx->object && start_cap_ob->type == OB_MESH) {
+ if (start_cap_ob && start_cap_ob != ctx->object) {
vgroup_start_cap_remap = BKE_object_defgroup_index_map_create(
start_cap_ob, ctx->object, &vgroup_start_cap_remap_len);
@@ -408,7 +408,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
}
}
Object *end_cap_ob = amd->end_cap;
- if (end_cap_ob && end_cap_ob != ctx->object && end_cap_ob->type == OB_MESH) {
+ if (end_cap_ob && end_cap_ob != ctx->object) {
vgroup_end_cap_remap = BKE_object_defgroup_index_map_create(
end_cap_ob, ctx->object, &vgroup_end_cap_remap_len);
@@ -465,13 +465,10 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
if (amd->fit_type == MOD_ARR_FITCURVE && amd->curve_ob != NULL) {
Object *curve_ob = amd->curve_ob;
- Curve *cu = curve_ob->data;
- if (cu) {
- CurveCache *curve_cache = curve_ob->runtime.curve_cache;
- if (curve_cache != NULL && curve_cache->path != NULL) {
- float scale_fac = mat4_to_scale(curve_ob->obmat);
- length = scale_fac * curve_cache->path->totdist;
- }
+ CurveCache *curve_cache = curve_ob->runtime.curve_cache;
+ if (curve_cache != NULL && curve_cache->path != NULL) {
+ float scale_fac = mat4_to_scale(curve_ob->obmat);
+ length = scale_fac * curve_cache->path->totdist;
}
}
@@ -769,6 +766,31 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
return arrayModifier_doArray(amd, ctx, mesh);
}
+static bool isDisabled(const struct Scene *UNUSED(scene),
+ ModifierData *md,
+ bool UNUSED(useRenderParams))
+{
+ ArrayModifierData *amd = (ArrayModifierData *)md;
+
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the curve/mesh is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+
+ if (amd->curve_ob && amd->curve_ob->type != OB_CURVE) {
+ return true;
+ }
+ else if (amd->start_cap && amd->start_cap->type != OB_MESH) {
+ return true;
+ }
+ else if (amd->end_cap && amd->end_cap->type != OB_MESH) {
+ return true;
+ }
+
+ return false;
+}
+
ModifierTypeInfo modifierType_Array = {
/* name */ "Array",
/* structName */ "ArrayModifierData",
@@ -789,7 +811,7 @@ ModifierTypeInfo modifierType_Array = {
/* initData */ initData,
/* requiredDataMask */ NULL,
/* freeData */ NULL,
- /* isDisabled */ NULL,
+ /* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c
index dc4898c83ff..e55eeddbfa5 100644
--- a/source/blender/modifiers/intern/MOD_boolean.c
+++ b/source/blender/modifiers/intern/MOD_boolean.c
@@ -71,7 +71,12 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
{
BooleanModifierData *bmd = (BooleanModifierData *)md;
- return !bmd->object;
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the mesh is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ return !bmd->object || bmd->object->type != OB_MESH;
}
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index 1a6d172d2f9..cc91e345c8f 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -114,7 +114,7 @@ static void deformVerts(ModifierData *md,
}
}
- BKE_mesh_apply_vert_coords(mesh_src, vertexCos);
+ BKE_mesh_vert_coords_apply(mesh_src, vertexCos);
clothModifier_do(clmd, ctx->depsgraph, scene, ctx->object, mesh_src, vertexCos);
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index 1bbc25643a1..3d43c6de88e 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -120,7 +120,7 @@ static void deformVerts(ModifierData *md,
float current_time = 0;
unsigned int mvert_num = 0;
- BKE_mesh_apply_vert_coords(mesh_src, vertexCos);
+ BKE_mesh_vert_coords_apply(mesh_src, vertexCos);
BKE_mesh_calc_normals(mesh_src);
current_time = DEG_get_ctime(ctx->depsgraph);
diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c
index be1580f0d70..a234f468e45 100644
--- a/source/blender/modifiers/intern/MOD_correctivesmooth.c
+++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c
@@ -635,12 +635,12 @@ static void correctivesmooth_modifier_do(ModifierData *md,
if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) {
/* caller needs to do sanity check here */
csmd->bind_coords_num = numVerts;
- rest_coords = (const float(*)[3])csmd->bind_coords;
+ rest_coords = csmd->bind_coords;
}
else {
int me_numVerts;
- rest_coords = (const float(*)[3])((em) ? BKE_editmesh_vertexCos_get_orco(em, &me_numVerts) :
- BKE_mesh_vertexCos_get(ob->data, &me_numVerts));
+ rest_coords = em ? BKE_editmesh_vert_coords_alloc_orco(em, &me_numVerts) :
+ BKE_mesh_vert_coords_alloc(ob->data, &me_numVerts);
BLI_assert((unsigned int)me_numVerts == numVerts);
is_rest_coords_alloc = true;
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index 7a07d9b28eb..f9137572d6f 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -66,7 +66,12 @@ static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED
{
CurveModifierData *cmd = (CurveModifierData *)md;
- return !cmd->object;
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the curve is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ return !cmd->object || cmd->object->type != OB_CURVE;
}
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c
index c994a680fb0..bb032f9725c 100644
--- a/source/blender/modifiers/intern/MOD_datatransfer.c
+++ b/source/blender/modifiers/intern/MOD_datatransfer.c
@@ -141,9 +141,14 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
ModifierData *md,
bool UNUSED(useRenderParams))
{
- DataTransferModifierData *dtmd = (DataTransferModifierData *)md;
/* If no source object, bypass. */
- return (dtmd->ob_source == NULL);
+ DataTransferModifierData *dtmd = (DataTransferModifierData *)md;
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the mesh is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ return !dtmd->ob_source || dtmd->ob_source->type != OB_MESH;
}
#define HIGH_POLY_WARNING 10000
diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c
index 3083d89d555..587aa108fd1 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim_util.c
+++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c
@@ -290,7 +290,7 @@ static Mesh *fluidsim_read_obj(const char *filename, const MPoly *mp_example)
gzclose(gzf);
BKE_mesh_calc_edges(mesh, false, false);
- BKE_mesh_apply_vert_normals(mesh, (short(*)[3])normals);
+ BKE_mesh_vert_normals_apply(mesh, (short(*)[3])normals);
MEM_freeN(normals);
// CDDM_calc_normals(result);
diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.h b/source/blender/modifiers/intern/MOD_fluidsim_util.h
index 0d2be3e7074..da70568353e 100644
--- a/source/blender/modifiers/intern/MOD_fluidsim_util.h
+++ b/source/blender/modifiers/intern/MOD_fluidsim_util.h
@@ -27,8 +27,6 @@
struct FluidsimModifierData;
struct Mesh;
struct ModifierEvalContext;
-struct Object;
-struct Scene;
/* new fluid-modifier interface */
void fluidsim_init(struct FluidsimModifierData *fluidmd);
diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c
index b639e874a88..a73e96da975 100644
--- a/source/blender/modifiers/intern/MOD_lattice.c
+++ b/source/blender/modifiers/intern/MOD_lattice.c
@@ -64,7 +64,12 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
{
LatticeModifierData *lmd = (LatticeModifierData *)md;
- return !lmd->object;
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the lattice is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ return !lmd->object || lmd->object->type != OB_LATTICE;
}
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c
index 3417aaeeb5c..df8f68862e6 100644
--- a/source/blender/modifiers/intern/MOD_mask.c
+++ b/source/blender/modifiers/intern/MOD_mask.c
@@ -138,10 +138,10 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
return mesh;
}
- /* Determine whether each vertexgroup is associated with a selected bone or not:
- * - Each cell is a boolean saying whether bone corresponding to the ith group is selected.
+ /* Determine whether each vertex-group is associated with a selected bone or not:
+ * - Each cell is a boolean saying whether bone corresponding to the i'th group selected.
* - Groups that don't match a bone are treated as not existing
- * (along with the corresponding ungrouped verts).
+ * (along with the corresponding un-grouped verts).
*/
bone_select_array = MEM_malloc_arrayN((size_t)defbase_tot, sizeof(char), "mask array");
@@ -344,6 +344,20 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
return result;
}
+static bool isDisabled(const struct Scene *UNUSED(scene),
+ ModifierData *md,
+ bool UNUSED(useRenderParams))
+{
+ MaskModifierData *mmd = (MaskModifierData *)md;
+
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the armature is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ return mmd->ob_arm && mmd->ob_arm->type != OB_ARMATURE;
+}
+
ModifierTypeInfo modifierType_Mask = {
/* name */ "Mask",
/* structName */ "MaskModifierData",
@@ -363,7 +377,7 @@ ModifierTypeInfo modifierType_Mask = {
/* initData */ NULL,
/* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
- /* isDisabled */ NULL,
+ /* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
/* dependsOnNormals */ NULL,
diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c
index da261b4f835..408e38f43ab 100644
--- a/source/blender/modifiers/intern/MOD_meshdeform.c
+++ b/source/blender/modifiers/intern/MOD_meshdeform.c
@@ -139,7 +139,12 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
{
MeshDeformModifierData *mmd = (MeshDeformModifierData *)md;
- return !mmd->object;
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the mesh is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ return !mmd->object || mmd->object->type != OB_MESH;
}
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
@@ -401,7 +406,7 @@ static void meshdeformModifier_do(ModifierData *md,
}
/* setup deformation data */
- cagecos = BKE_mesh_vertexCos_get(cagemesh, NULL);
+ cagecos = BKE_mesh_vert_coords_alloc(cagemesh, NULL);
bindcagecos = (float(*)[3])mmd->bindcagecos;
/* We allocate 1 element extra to make it possible to
diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c
index 760830ffb24..0f57b759e38 100644
--- a/source/blender/modifiers/intern/MOD_meshsequencecache.c
+++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c
@@ -114,10 +114,20 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
}
}
+ /* If this invocation is for the ORCO mesh, and the mesh in Alembic hasn't changed topology, we
+ * must return the mesh as-is instead of deforming it. */
+ if (ctx->flag & MOD_APPLY_ORCO &&
+ !ABC_mesh_topology_changed(mcmd->reader, ctx->object, mesh, time, &err_str)) {
+ return mesh;
+ }
+
if (me != NULL) {
MVert *mvert = mesh->mvert;
MEdge *medge = mesh->medge;
MPoly *mpoly = mesh->mpoly;
+
+ /* TODO(sybren+bastien): possibly check relevant custom data layers (UV/color depending on
+ * flags) and duplicate those too. */
if ((me->mvert == mvert) || (me->medge == medge) || (me->mpoly == mpoly)) {
/* We need to duplicate data here, otherwise we'll modify org mesh, see T51701. */
BKE_id_copy_ex(NULL,
diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c
index c64d9be1158..dd7c001931c 100644
--- a/source/blender/modifiers/intern/MOD_multires.c
+++ b/source/blender/modifiers/intern/MOD_multires.c
@@ -168,6 +168,10 @@ static Mesh *multires_as_ccg(MultiresModifierData *mmd,
static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
{
Mesh *result = mesh;
+#if !defined(WITH_OPENSUBDIV)
+ modifier_setError(md, "Disabled, built without OpenSubdiv");
+ return result;
+#endif
MultiresModifierData *mmd = (MultiresModifierData *)md;
SubdivSettings subdiv_settings;
BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 71913378277..49bb8691764 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -80,7 +80,12 @@ static bool isDisabled(const struct Scene *scene, ModifierData *md, bool useRend
ParticleSystem *psys;
ModifierData *ob_md;
- if (!pimd->ob) {
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the mesh is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ if (!pimd->ob || pimd->ob->type != OB_MESH) {
return true;
}
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
index 021e61bd46d..a7c7c207cd6 100644
--- a/source/blender/modifiers/intern/MOD_particlesystem.c
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -152,7 +152,7 @@ static void deformVerts(ModifierData *md,
/* make new mesh */
psmd->mesh_final = BKE_mesh_copy_for_eval(mesh_src, false);
- BKE_mesh_apply_vert_coords(psmd->mesh_final, vertexCos);
+ BKE_mesh_vert_coords_apply(psmd->mesh_final, vertexCos);
BKE_mesh_calc_normals(psmd->mesh_final);
BKE_mesh_tessface_ensure(psmd->mesh_final);
diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c
index 23da1ec2754..631401d9d9e 100644
--- a/source/blender/modifiers/intern/MOD_remesh.c
+++ b/source/blender/modifiers/intern/MOD_remesh.c
@@ -105,7 +105,7 @@ static void dualcon_add_vert(void *output_v, const float co[3])
DualConOutput *output = output_v;
Mesh *mesh = output->mesh;
- assert(output->curvert < mesh->totvert);
+ BLI_assert(output->curvert < mesh->totvert);
copy_v3_v3(mesh->mvert[output->curvert].co, co);
output->curvert++;
@@ -119,7 +119,7 @@ static void dualcon_add_quad(void *output_v, const int vert_indices[4])
MPoly *cur_poly;
int i;
- assert(output->curface < mesh->totpoly);
+ BLI_assert(output->curface < mesh->totpoly);
mloop = mesh->mloop;
cur_poly = &mesh->mpoly[output->curface];
diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c
index 07182d82fdc..4bca48852a2 100644
--- a/source/blender/modifiers/intern/MOD_shrinkwrap.c
+++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c
@@ -75,7 +75,19 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
bool UNUSED(useRenderParams))
{
ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
- return !smd->target;
+
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the mesh is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ if (!smd->target || smd->target->type != OB_MESH) {
+ return true;
+ }
+ else if (smd->auxTarget && smd->auxTarget->type != OB_MESH) {
+ return true;
+ }
+ return false;
}
static void foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index 0b1249e263c..08a884fa879 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -208,6 +208,10 @@ static SubsurfRuntimeData *subsurf_ensure_runtime(SubsurfModifierData *smd)
static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh)
{
Mesh *result = mesh;
+#if !defined(WITH_OPENSUBDIV)
+ modifier_setError(md, "Disabled, built without OpenSubdiv");
+ return result;
+#endif
SubsurfModifierData *smd = (SubsurfModifierData *)md;
SubdivSettings subdiv_settings;
subdiv_settings_init(&subdiv_settings, smd);
diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c
index dcc6371e024..840914aa313 100644
--- a/source/blender/modifiers/intern/MOD_surface.c
+++ b/source/blender/modifiers/intern/MOD_surface.c
@@ -130,7 +130,7 @@ static void deformVerts(ModifierData *md,
float *vec;
MVert *x, *v;
- BKE_mesh_apply_vert_coords(surmd->mesh, vertexCos);
+ BKE_mesh_vert_coords_apply(surmd->mesh, vertexCos);
BKE_mesh_calc_normals(surmd->mesh);
numverts = surmd->mesh->totvert;
diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index c428325e42b..b34688d27d6 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -1279,7 +1279,13 @@ static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED
{
SurfaceDeformModifierData *smd = (SurfaceDeformModifierData *)md;
- return smd->target == NULL && !(smd->verts != NULL && !(smd->flags & MOD_SDEF_BIND));
+ /* The object type check is only needed here in case we have a placeholder
+ * object assigned (because the library containing the mesh is missing).
+ *
+ * In other cases it should be impossible to have a type mismatch.
+ */
+ return (smd->target == NULL || smd->target->type != OB_MESH) &&
+ !(smd->verts != NULL && !(smd->flags & MOD_SDEF_BIND));
}
ModifierTypeInfo modifierType_SurfaceDeform = {
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 452c9ff945d..71163388707 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -198,7 +198,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
/* TODO(sybren): after modifier conversion of DM to Mesh is done, check whether
* we really need vertexCos here. */
if (vertexCos) {
- BKE_mesh_apply_vert_coords(mesh, vertexCos);
+ BKE_mesh_vert_coords_apply(mesh, vertexCos);
mesh->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
}
diff --git a/source/blender/modifiers/intern/MOD_util.h b/source/blender/modifiers/intern/MOD_util.h
index ba3ca44c026..e1991de3bb8 100644
--- a/source/blender/modifiers/intern/MOD_util.h
+++ b/source/blender/modifiers/intern/MOD_util.h
@@ -31,8 +31,6 @@ struct Mesh;
struct ModifierData;
struct ModifierEvalContext;
struct Object;
-struct Scene;
-struct Tex;
void MOD_init_texture(struct MappingInfoModifierData *dmd, const struct ModifierEvalContext *ctx);
void MOD_get_texture_coords(struct MappingInfoModifierData *dmd,
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index f9eb92cd132..5f1eae0297a 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -204,7 +204,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
mloop_uv = CustomData_duplicate_referenced_layer_named(
&mesh->ldata, CD_MLOOPUV, uvname, numLoops);
- coords = BKE_mesh_vertexCos_get(mesh, &numVerts);
+ coords = BKE_mesh_vert_coords_alloc(mesh, &numVerts);
/* convert coords to world space */
for (i = 0, co = coords; i < numVerts; ++i, ++co) {
diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c
index 86d1b310d0c..95b15b4a924 100644
--- a/source/blender/modifiers/intern/MOD_weightvgproximity.c
+++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c
@@ -492,7 +492,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(mesh, NULL);
+ float(*tv_cos)[3] = BKE_mesh_vert_coords_alloc(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]]);
@@ -500,7 +500,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes
MEM_freeN(tv_cos);
}
else {
- v_cos = BKE_mesh_vertexCos_get(mesh, NULL);
+ v_cos = BKE_mesh_vert_coords_alloc(mesh, NULL);
}
/* Compute wanted distances. */
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 284eaa8b70b..5cf5e1ac6d3 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -200,14 +200,16 @@ set(SRC
shader/nodes/node_shader_tex_sky.c
shader/nodes/node_shader_tex_voronoi.c
shader/nodes/node_shader_tex_wave.c
+ shader/nodes/node_shader_tex_white_noise.c
shader/nodes/node_shader_uvAlongStroke.c
shader/nodes/node_shader_uvmap.c
shader/nodes/node_shader_valToRgb.c
shader/nodes/node_shader_value.c
- shader/nodes/node_shader_vectMath.c
+ shader/nodes/node_shader_vector_math.c
shader/nodes/node_shader_vectTransform.c
shader/nodes/node_shader_vector_displacement.c
shader/nodes/node_shader_volume_absorption.c
+ shader/nodes/node_shader_volume_info.c
shader/nodes/node_shader_volume_principled.c
shader/nodes/node_shader_volume_scatter.c
shader/nodes/node_shader_wavelength.c
diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h
index 9349a428021..30673e7cd31 100644
--- a/source/blender/nodes/NOD_shader.h
+++ b/source/blender/nodes/NOD_shader.h
@@ -81,6 +81,7 @@ void register_node_type_sh_layer_weight(void);
void register_node_type_sh_tex_coord(void);
void register_node_type_sh_particle_info(void);
void register_node_type_sh_hair_info(void);
+void register_node_type_sh_volume_info(void);
void register_node_type_sh_script(void);
void register_node_type_sh_normal_map(void);
void register_node_type_sh_tangent(void);
@@ -131,6 +132,7 @@ void register_node_type_sh_tex_noise(void);
void register_node_type_sh_tex_checker(void);
void register_node_type_sh_bump(void);
void register_node_type_sh_tex_ies(void);
+void register_node_type_sh_tex_white_noise(void);
void register_node_type_sh_custom_group(bNodeType *ntype);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index c72e97642a2..d14511504f0 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -53,7 +53,7 @@ DefNode(ShaderNode, SH_NODE_CAMERA, 0, "CAMERA
DefNode(ShaderNode, SH_NODE_MAP_RANGE, def_map_range, "MAP_RANGE", MapRange, "Map Range", "" )
DefNode(ShaderNode, SH_NODE_CLAMP, 0, "CLAMP", Clamp, "Clamp", "" )
DefNode(ShaderNode, SH_NODE_MATH, def_math, "MATH", Math, "Math", "" )
-DefNode(ShaderNode, SH_NODE_VECT_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" )
+DefNode(ShaderNode, SH_NODE_VECTOR_MATH, def_vector_math, "VECT_MATH", VectorMath, "Vector Math", "" )
DefNode(ShaderNode, SH_NODE_SQUEEZE, 0, "SQUEEZE", Squeeze, "Squeeze Value", "" )
DefNode(ShaderNode, SH_NODE_INVERT, 0, "INVERT", Invert, "Invert", "" )
DefNode(ShaderNode, SH_NODE_SEPRGB, 0, "SEPRGB", SeparateRGB, "Separate RGB", "" )
@@ -96,6 +96,7 @@ DefNode(ShaderNode, SH_NODE_LIGHT_FALLOFF, 0, "LIG
DefNode(ShaderNode, SH_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "" )
DefNode(ShaderNode, SH_NODE_PARTICLE_INFO, 0, "PARTICLE_INFO", ParticleInfo, "Particle Info", "" )
DefNode(ShaderNode, SH_NODE_HAIR_INFO, 0, "HAIR_INFO", HairInfo, "Hair Info", "" )
+DefNode(ShaderNode, SH_NODE_VOLUME_INFO, 0, "VOLUME_INFO", VolumeInfo, "Volume Info", "" )
DefNode(ShaderNode, SH_NODE_WIREFRAME, def_sh_tex_wireframe, "WIREFRAME", Wireframe, "Wireframe", "" )
DefNode(ShaderNode, SH_NODE_WAVELENGTH, 0, "WAVELENGTH", Wavelength, "Wavelength", "" )
DefNode(ShaderNode, SH_NODE_BLACKBODY, 0, "BLACKBODY", Blackbody, "Blackbody", "" )
@@ -127,6 +128,7 @@ DefNode(ShaderNode, SH_NODE_BEVEL, def_sh_bevel, "BEV
DefNode(ShaderNode, SH_NODE_DISPLACEMENT, def_sh_displacement, "DISPLACEMENT", Displacement, "Displacement", "" )
DefNode(ShaderNode, SH_NODE_VECTOR_DISPLACEMENT,def_sh_vector_displacement,"VECTOR_DISPLACEMENT",VectorDisplacement,"Vector Displacement","" )
DefNode(ShaderNode, SH_NODE_TEX_IES, def_sh_tex_ies, "TEX_IES", TexIES, "IES Texture", "" )
+DefNode(ShaderNode, SH_NODE_TEX_WHITE_NOISE, def_sh_tex_white_noise, "TEX_WHITE_NOISE", TexWhiteNoise, "White Noise", "" )
DefNode(CompositorNode, CMP_NODE_VIEWER, def_cmp_viewer, "VIEWER", Viewer, "Viewer", "" )
DefNode(CompositorNode, CMP_NODE_RGB, 0, "RGB", RGB, "RGB", "" )
diff --git a/source/blender/nodes/composite/nodes/node_composite_denoise.c b/source/blender/nodes/composite/nodes/node_composite_denoise.c
index e2fdb08816a..bb62869f470 100644
--- a/source/blender/nodes/composite/nodes/node_composite_denoise.c
+++ b/source/blender/nodes/composite/nodes/node_composite_denoise.c
@@ -33,8 +33,8 @@
static bNodeSocketTemplate cmp_node_denoise_in[] = {
{SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
- {SOCK_RGBA, 1, N_("Albedo"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
{SOCK_VECTOR, 0, N_("Normal"), 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 1.0f},
+ {SOCK_RGBA, 1, N_("Albedo"), 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
{-1, 0, ""}};
static bNodeSocketTemplate cmp_node_denoise_out[] = {{SOCK_RGBA, 0, N_("Image")}, {-1, 0, ""}};
diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
index faf9e20da51..af806a37341 100644
--- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c
+++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c
@@ -191,7 +191,7 @@ void ntreeCompositOutputFileSetLayer(bNode *node, bNodeSocket *sock, const char
static void init_output_file(const bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = ptr->data;
NodeImageMultiFile *nimf = MEM_callocN(sizeof(NodeImageMultiFile), "node image multi file");
ImageFormatData *format = NULL;
diff --git a/source/blender/nodes/composite/nodes/node_composite_switchview.c b/source/blender/nodes/composite/nodes/node_composite_switchview.c
index 92e06307afb..cecd8204f4a 100644
--- a/source/blender/nodes/composite/nodes/node_composite_switchview.c
+++ b/source/blender/nodes/composite/nodes/node_composite_switchview.c
@@ -116,7 +116,7 @@ static void cmp_node_switch_view_update(bNodeTree *ntree, bNode *node)
static void init_switch_view(const bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
- bNodeTree *ntree = ptr->id.data;
+ bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = ptr->data;
SceneRenderView *srv;
bNodeSocket *sock;
diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c
index 8aeada7bde0..3485bd41660 100644
--- a/source/blender/nodes/intern/node_socket.c
+++ b/source/blender/nodes/intern/node_socket.c
@@ -39,8 +39,6 @@
#include "NOD_socket.h"
-struct Main;
-
struct bNodeSocket *node_add_socket_from_template(struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocketTemplate *stemp,
diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c
index e9a825b5b3f..0d7f19fb67a 100644
--- a/source/blender/nodes/intern/node_util.c
+++ b/source/blender/nodes/intern/node_util.c
@@ -100,7 +100,7 @@ void node_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int max
BLI_strncpy(label, IFACE_(name), maxlen);
}
-void node_vect_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
+void node_vector_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen)
{
const char *name;
RNA_enum_name(rna_enum_node_vec_math_items, node->custom1, &name);
diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h
index 7eef70db498..49117b38aba 100644
--- a/source/blender/nodes/intern/node_util.h
+++ b/source/blender/nodes/intern/node_util.h
@@ -71,7 +71,7 @@ extern void *node_initexec_curves(struct bNodeExecContext *context,
void node_blend_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
void node_image_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
void node_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
-void node_vect_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
+void node_vector_math_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
void node_filter_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen);
/*** Link Handling */
diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c
index 4891fb323ad..41f13087f67 100644
--- a/source/blender/nodes/shader/node_shader_tree.c
+++ b/source/blender/nodes/shader/node_shader_tree.c
@@ -799,13 +799,15 @@ static void ntree_shader_relink_displacement(bNodeTree *ntree, bNode *output_nod
nodeRemLink(ntree, displacement_link);
/* Convert displacement vector to bump height. */
- bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECT_MATH);
+ bNode *dot_node = nodeAddStaticNode(NULL, ntree, SH_NODE_VECTOR_MATH);
bNode *geo_node = nodeAddStaticNode(NULL, ntree, SH_NODE_NEW_GEOMETRY);
bNodeSocket *normal_socket = ntree_shader_node_find_output(geo_node, "Normal");
- dot_node->custom1 = 3; /* dot product */
+ bNodeSocket *dot_input1 = dot_node->inputs.first;
+ bNodeSocket *dot_input2 = dot_input1->next;
+ dot_node->custom1 = NODE_VECTOR_MATH_DOT_PRODUCT;
- nodeAddLink(ntree, displacement_node, displacement_socket, dot_node, dot_node->inputs.first);
- nodeAddLink(ntree, geo_node, normal_socket, dot_node, dot_node->inputs.last);
+ nodeAddLink(ntree, displacement_node, displacement_socket, dot_node, dot_input1);
+ nodeAddLink(ntree, geo_node, normal_socket, dot_node, dot_input2);
displacement_node = dot_node;
displacement_socket = ntree_shader_node_find_output(dot_node, "Value");
diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c
index 2e8f81979a8..65676a5ea91 100644
--- a/source/blender/nodes/shader/node_shader_util.c
+++ b/source/blender/nodes/shader/node_shader_util.c
@@ -283,7 +283,7 @@ void node_shader_gpu_tex_mapping(GPUMaterial *mat,
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);
+ GPU_link(mat, "vector_normalize", in[0].link, &in[0].link);
}
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mapping.c b/source/blender/nodes/shader/nodes/node_shader_mapping.c
index eca0d96f2c8..e58a5d72f28 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mapping.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mapping.c
@@ -115,7 +115,7 @@ static int gpu_shader_mapping(GPUMaterial *mat,
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);
+ GPU_link(mat, "vector_normalize", out[0].link, &out[0].link);
}
return true;
diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c
index 29c6d855eae..aaedc4aa1b7 100644
--- a/source/blender/nodes/shader/nodes/node_shader_math.c
+++ b/source/blender/nodes/shader/nodes/node_shader_math.c
@@ -31,272 +31,6 @@ static bNodeSocketTemplate sh_node_math_in[] = {
static bNodeSocketTemplate sh_node_math_out[] = {{SOCK_FLOAT, 0, N_("Value")}, {-1, 0, ""}};
-static void node_shader_exec_math(void *UNUSED(data),
- int UNUSED(thread),
- bNode *node,
- bNodeExecData *UNUSED(execdata),
- bNodeStack **in,
- bNodeStack **out)
-{
- float a, b, r = 0.0f;
-
- nodestack_get_vec(&a, SOCK_FLOAT, in[0]);
- nodestack_get_vec(&b, SOCK_FLOAT, in[1]);
-
- switch (node->custom1) {
-
- case NODE_MATH_ADD:
- r = a + b;
- break;
- case NODE_MATH_SUB:
- r = a - b;
- break;
- case NODE_MATH_MUL:
- r = a * b;
- break;
- case NODE_MATH_DIVIDE: {
- if (b == 0) { /* We don't want to divide by zero. */
- r = 0.0;
- }
- else {
- r = a / b;
- }
- break;
- }
- case NODE_MATH_SIN: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- r = sinf(a);
- }
- else {
- r = sinf(b);
- }
- break;
- }
- case NODE_MATH_COS: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- r = cosf(a);
- }
- else {
- r = cosf(b);
- }
- break;
- }
- case NODE_MATH_TAN: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- r = tanf(a);
- }
- else {
- r = tanf(b);
- }
- break;
- }
- case NODE_MATH_ASIN: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- /* Can't do the impossible... */
- if (a <= 1 && a >= -1) {
- r = asinf(a);
- }
- else {
- r = 0.0;
- }
- }
- else {
- /* Can't do the impossible... */
- if (b <= 1 && b >= -1) {
- r = asinf(b);
- }
- else {
- r = 0.0;
- }
- }
- break;
- }
- case NODE_MATH_ACOS: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- /* Can't do the impossible... */
- if (a <= 1 && a >= -1) {
- r = acosf(a);
- }
- else {
- r = 0.0;
- }
- }
- else {
- /* Can't do the impossible... */
- if (b <= 1 && b >= -1) {
- r = acosf(b);
- }
- else {
- r = 0.0;
- }
- }
- break;
- }
- case NODE_MATH_ATAN: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- r = atan(a);
- }
- else {
- r = atan(b);
- }
- break;
- }
- case NODE_MATH_POW: {
- /* Only raise negative numbers by full integers */
- if (a >= 0) {
- r = pow(a, b);
- }
- else {
- float y_mod_1 = fabsf(fmodf(b, 1.0f));
-
- /* if input value is not nearly an integer,
- * fall back to zero, nicer than straight rounding. */
- if (y_mod_1 > 0.999f || y_mod_1 < 0.001f) {
- r = powf(a, floorf(b + 0.5f));
- }
- else {
- r = 0.0f;
- }
- }
-
- break;
- }
- case NODE_MATH_LOG: {
- /* Don't want any imaginary numbers... */
- if (a > 0 && b > 0) {
- r = log(a) / log(b);
- }
- else {
- r = 0.0;
- }
- break;
- }
- case NODE_MATH_MIN: {
- if (a < b) {
- r = a;
- }
- else {
- r = b;
- }
- break;
- }
- case NODE_MATH_MAX: {
- if (a > b) {
- r = a;
- }
- else {
- r = b;
- }
- break;
- }
- case NODE_MATH_ROUND: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- r = (a < 0) ? (int)(a - 0.5f) : (int)(a + 0.5f);
- }
- else {
- r = (b < 0) ? (int)(b - 0.5f) : (int)(b + 0.5f);
- }
- break;
- }
- case NODE_MATH_LESS: {
- if (a < b) {
- r = 1.0f;
- }
- else {
- r = 0.0f;
- }
- break;
- }
- case NODE_MATH_GREATER: {
- if (a > b) {
- r = 1.0f;
- }
- else {
- r = 0.0f;
- }
- break;
- }
- case NODE_MATH_MOD: {
- if (b == 0.0f) {
- r = 0.0f;
- }
- else {
- r = fmod(a, b);
- }
- break;
- }
- case NODE_MATH_ABS: {
- r = fabsf(a);
- break;
- }
- case NODE_MATH_ATAN2: {
- r = atan2(a, b);
- break;
- }
- case NODE_MATH_FLOOR: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- r = floorf(a);
- }
- else {
- r = floorf(b);
- }
- break;
- }
- case NODE_MATH_CEIL: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- r = ceilf(a);
- }
- else {
- r = ceilf(b);
- }
- break;
- }
- case NODE_MATH_FRACT: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- r = a - floorf(a);
- }
- else {
- r = b - floorf(b);
- }
- break;
- }
- case NODE_MATH_SQRT: {
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- if (a > 0) {
- r = sqrt(a);
- }
- else {
- r = 0.0;
- }
- }
- else {
- if (b > 0) {
- r = sqrt(b);
- }
- else {
- r = 0.0;
- }
- }
- break;
- }
- }
- if (node->custom2 & SHD_MATH_CLAMP) {
- CLAMP(r, 0.0f, 1.0f);
- }
- out[0]->vec[0] = r;
-}
-
static int gpu_shader_math(GPUMaterial *mat,
bNode *node,
bNodeExecData *UNUSED(execdata),
@@ -304,68 +38,65 @@ static int gpu_shader_math(GPUMaterial *mat,
GPUNodeStack *out)
{
static const char *names[] = {
- "math_add", "math_subtract", "math_multiply", "math_divide", "math_sine",
- "math_cosine", "math_tangent", "math_asin", "math_acos", "math_atan",
- "math_pow", "math_log", "math_min", "math_max", "math_round",
- "math_less_than", "math_greater_than", "math_modulo", "math_abs", "math_atan2",
- "math_floor", "math_ceil", "math_fract", "math_sqrt",
+ [NODE_MATH_ADD] = "math_add",
+ [NODE_MATH_SUBTRACT] = "math_subtract",
+ [NODE_MATH_MULTIPLY] = "math_multiply",
+ [NODE_MATH_DIVIDE] = "math_divide",
+
+ [NODE_MATH_POWER] = "math_power",
+ [NODE_MATH_LOGARITHM] = "math_logarithm",
+ [NODE_MATH_SQRT] = "math_sqrt",
+ [NODE_MATH_ABSOLUTE] = "math_absolute",
+
+ [NODE_MATH_MINIMUM] = "math_minimum",
+ [NODE_MATH_MAXIMUM] = "math_maximum",
+ [NODE_MATH_LESS_THAN] = "math_less_than",
+ [NODE_MATH_GREATER_THAN] = "math_greater_than",
+
+ [NODE_MATH_ROUND] = "math_round",
+ [NODE_MATH_FLOOR] = "math_floor",
+ [NODE_MATH_CEIL] = "math_ceil",
+ [NODE_MATH_FRACTION] = "math_fraction",
+ [NODE_MATH_MODULO] = "math_modulo",
+
+ [NODE_MATH_SINE] = "math_sine",
+ [NODE_MATH_COSINE] = "math_cosine",
+ [NODE_MATH_TANGENT] = "math_tangent",
+ [NODE_MATH_ARCSINE] = "math_arcsine",
+ [NODE_MATH_ARCCOSINE] = "math_arccosine",
+ [NODE_MATH_ARCTANGENT] = "math_arctangent",
+ [NODE_MATH_ARCTAN2] = "math_arctan2",
};
- switch (node->custom1) {
- case NODE_MATH_ADD:
- case NODE_MATH_SUB:
- case NODE_MATH_MUL:
- case NODE_MATH_DIVIDE:
- case NODE_MATH_POW:
- case NODE_MATH_LOG:
- case NODE_MATH_MIN:
- case NODE_MATH_MAX:
- case NODE_MATH_LESS:
- case NODE_MATH_GREATER:
- case NODE_MATH_MOD:
- case NODE_MATH_ATAN2:
- GPU_stack_link(mat, node, names[node->custom1], in, out);
- break;
- case NODE_MATH_SIN:
- case NODE_MATH_COS:
- case NODE_MATH_TAN:
- case NODE_MATH_ASIN:
- case NODE_MATH_ACOS:
- case NODE_MATH_ATAN:
- case NODE_MATH_ROUND:
- case NODE_MATH_ABS:
- case NODE_MATH_FLOOR:
- case NODE_MATH_FRACT:
- case NODE_MATH_CEIL:
- case NODE_MATH_SQRT:
- if (in[0].hasinput || !in[1].hasinput) {
- /* use only first item and terminator */
- GPUNodeStack tmp_in[2];
- memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack));
- memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
- GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
- }
- else {
- /* use only second item and terminator */
- GPUNodeStack tmp_in[2];
- memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack));
- memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
- GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
- }
- break;
- default:
- return 0;
- }
+ GPU_stack_link(mat, node, names[node->custom1], in, out);
if (node->custom2 & SHD_MATH_CLAMP) {
float min[3] = {0.0f, 0.0f, 0.0f};
float max[3] = {1.0f, 1.0f, 1.0f};
GPU_link(mat, "clamp_value", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link);
}
-
return 1;
}
+static void node_shader_update_math(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sock = BLI_findlink(&node->inputs, 1);
+ nodeSetSocketAvailability(sock,
+ !ELEM(node->custom1,
+ NODE_MATH_SQRT,
+ NODE_MATH_CEIL,
+ NODE_MATH_SINE,
+ NODE_MATH_ROUND,
+ NODE_MATH_FLOOR,
+ NODE_MATH_COSINE,
+ NODE_MATH_ARCSINE,
+ NODE_MATH_TANGENT,
+ NODE_MATH_ABSOLUTE,
+ NODE_MATH_FRACTION,
+ NODE_MATH_ARCCOSINE,
+ NODE_MATH_ARCTANGENT));
+}
+
void register_node_type_sh_math(void)
{
static bNodeType ntype;
@@ -373,9 +104,8 @@ void register_node_type_sh_math(void)
sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0);
node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out);
node_type_label(&ntype, node_math_label);
- node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL, NULL, node_shader_exec_math);
node_type_gpu(&ntype, gpu_shader_math);
+ node_type_update(&ntype, node_shader_update_math);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
index 872f4f9da9c..ae2184d8237 100644
--- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
+++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c
@@ -92,7 +92,7 @@ static int gpu_shader_mix_rgb(GPUMaterial *mat,
if (ret && node->custom2 & SHD_MIXRGB_CLAMP) {
float min[3] = {0.0f, 0.0f, 0.0f};
float max[3] = {1.0f, 1.0f, 1.0f};
- GPU_link(mat, "clamp_vec3", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link);
+ GPU_link(mat, "clamp_color", out[0].link, GPU_constant(min), GPU_constant(max), &out[0].link);
}
return ret;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_normal.c b/source/blender/nodes/shader/nodes/node_shader_normal.c
index 074cc3dd87f..9dd89258446 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal.c
@@ -25,7 +25,7 @@
/* **************** NORMAL ******************** */
static bNodeSocketTemplate sh_node_normal_in[] = {
- {SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_DIRECTION},
+ {SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, PROP_DIRECTION},
{-1, 0, ""},
};
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 4976d038065..18015d94f03 100644
--- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c
+++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c
@@ -58,7 +58,7 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
GPUNodeLink *realnorm;
GPUNodeLink *strength;
- float d[4] = {0, 0, 0, 0};
+ float strength_min[4] = {0, 0, 0, 0};
if (in[0].link) {
strength = in[0].link;
@@ -85,7 +85,7 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
}
negnorm = GPU_builtin(GPU_WORLD_NORMAL);
- GPU_link(mat, "math_max", strength, GPU_constant(d), &strength);
+ GPU_link(mat, "math_maximum", strength, GPU_constant(strength_min), &strength);
const char *color_to_normal_fnc_name = "color_to_normal_new_shading";
if (nm->space == SHD_SPACE_BLENDER_OBJECT || nm->space == SHD_SPACE_BLENDER_WORLD) {
@@ -114,8 +114,8 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
break;
}
- GPU_link(mat, "vec_math_mix", strength, realnorm, negnorm, &out[0].link);
- GPU_link(mat, "vect_normalize", out[0].link, &out[0].link);
+ GPU_link(mat, "vector_mix", strength, realnorm, negnorm, &out[0].link);
+ GPU_link(mat, "vector_normalize", out[0].link, &out[0].link);
return true;
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_object_info.c b/source/blender/nodes/shader/nodes/node_shader_object_info.c
index 118b8136693..58449a53706 100644
--- a/source/blender/nodes/shader/nodes/node_shader_object_info.c
+++ b/source/blender/nodes/shader/nodes/node_shader_object_info.c
@@ -23,6 +23,7 @@
static bNodeSocketTemplate sh_node_object_info_out[] = {
{SOCK_VECTOR, 0, N_("Location"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ {SOCK_RGBA, 0, N_("Color"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{SOCK_FLOAT, 0, N_("Object Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{SOCK_FLOAT, 0, N_("Material Index"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
{SOCK_FLOAT, 0, N_("Random"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
@@ -36,38 +37,25 @@ static int node_shader_gpu_object_info(GPUMaterial *mat,
GPUNodeStack *out)
{
Material *ma = GPU_material_get_material(mat);
- /* Convert to float. */
- float index = ma ? ma->index : 0;
+ float index = ma ? ma->index : 0.0f;
return GPU_stack_link(mat,
node,
"node_object_info",
in,
out,
GPU_builtin(GPU_OBJECT_MATRIX),
+ GPU_builtin(GPU_OBJECT_COLOR),
GPU_builtin(GPU_OBJECT_INFO),
GPU_constant(&index));
}
-static void node_shader_exec_object_info(void *UNUSED(data),
- int UNUSED(thread),
- bNode *UNUSED(node),
- bNodeExecData *UNUSED(execdata),
- bNodeStack **UNUSED(in),
- bNodeStack **UNUSED(out))
-{
-}
-
-/* node type definition */
void register_node_type_sh_object_info(void)
{
static bNodeType ntype;
sh_node_type_base(&ntype, SH_NODE_OBJECT_INFO, "Object Info", NODE_CLASS_INPUT, 0);
node_type_socket_templates(&ntype, NULL, sh_node_object_info_out);
- node_type_init(&ntype, NULL);
- node_type_storage(&ntype, "", NULL, NULL);
node_type_gpu(&ntype, node_shader_gpu_object_info);
- node_type_exec(&ntype, NULL, NULL, node_shader_exec_object_info);
nodeRegisterType(&ntype);
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index bd8355ec885..a02262950a8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -124,15 +124,15 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) ||
IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) {
/* Don't let alpha affect color output in these cases. */
- GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
}
else {
/* Always output with premultiplied alpha. */
if (ima->alpha_mode == IMA_ALPHA_PREMUL) {
- GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
}
else {
- GPU_link(mat, "tex_color_alpha_premultiply", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link);
}
}
}
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 6f3614e357d..5eaf09659d8 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -183,7 +183,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) ||
IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) {
/* Don't let alpha affect color output in these cases. */
- GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
}
else {
/* Output premultiplied alpha depending on alpha socket usage. This makes
@@ -192,18 +192,18 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
* not, then there will be no artifacts from zero alpha areas. */
if (ima->alpha_mode == IMA_ALPHA_PREMUL) {
if (out[1].hasoutput) {
- GPU_link(mat, "tex_color_alpha_unpremultiply", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_unpremultiply", out[0].link, &out[0].link);
}
else {
- GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
}
}
else {
if (out[1].hasoutput) {
- GPU_link(mat, "tex_color_alpha_clear", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_clear", out[0].link, &out[0].link);
}
else {
- GPU_link(mat, "tex_color_alpha_premultiply", out[0].link, &out[0].link);
+ GPU_link(mat, "color_alpha_premultiply", out[0].link, &out[0].link);
}
}
}
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c
new file mode 100644
index 00000000000..c0f9a033476
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c
@@ -0,0 +1,76 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+#include "../node_shader_util.h"
+
+/* **************** WHITE NOISE **************** */
+
+static bNodeSocketTemplate sh_node_tex_white_noise_in[] = {
+ {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_NONE},
+ {SOCK_FLOAT, 1, N_("W"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f, PROP_NONE},
+ {-1, 0, ""}};
+
+static bNodeSocketTemplate sh_node_tex_white_noise_out[] = {
+ {SOCK_FLOAT, 0, N_("Value")},
+ {-1, 0, ""},
+};
+
+static void node_shader_init_tex_white_noise(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ node->custom1 = 3;
+}
+
+static int gpu_shader_tex_white_noise(GPUMaterial *mat,
+ bNode *node,
+ bNodeExecData *UNUSED(execdata),
+ GPUNodeStack *in,
+ GPUNodeStack *out)
+{
+ static const char *names[] = {
+ "",
+ "node_white_noise_1d",
+ "node_white_noise_2d",
+ "node_white_noise_3d",
+ "node_white_noise_4d",
+ };
+
+ return GPU_stack_link(mat, node, names[node->custom1], in, out);
+}
+
+static void node_shader_update_tex_white_noise(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sockVector = nodeFindSocket(node, SOCK_IN, "Vector");
+ bNodeSocket *sockW = nodeFindSocket(node, SOCK_IN, "W");
+
+ nodeSetSocketAvailability(sockVector, node->custom1 != 1);
+ nodeSetSocketAvailability(sockW, node->custom1 == 1 || node->custom1 == 4);
+}
+
+void register_node_type_sh_tex_white_noise(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE, 0);
+ node_type_socket_templates(&ntype, sh_node_tex_white_noise_in, sh_node_tex_white_noise_out);
+ node_type_init(&ntype, node_shader_init_tex_white_noise);
+ node_type_gpu(&ntype, gpu_shader_tex_white_noise);
+ node_type_update(&ntype, node_shader_update_tex_white_noise);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_vectMath.c b/source/blender/nodes/shader/nodes/node_shader_vectMath.c
deleted file mode 100644
index 41273a6dc1d..00000000000
--- a/source/blender/nodes/shader/nodes/node_shader_vectMath.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2005 Blender Foundation.
- * All rights reserved.
- */
-
-/** \file
- * \ingroup shdnodes
- */
-
-#include "node_shader_util.h"
-
-/* **************** VECTOR MATH ******************** */
-static bNodeSocketTemplate sh_node_vect_math_in[] = {
- {SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
- {SOCK_VECTOR, 1, N_("Vector"), 0.5f, 0.5f, 0.5f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
- {-1, 0, ""}};
-
-static bNodeSocketTemplate sh_node_vect_math_out[] = {
- {SOCK_VECTOR, 0, N_("Vector")}, {SOCK_FLOAT, 0, N_("Value")}, {-1, 0, ""}};
-
-static void node_shader_exec_vect_math(void *UNUSED(data),
- int UNUSED(thread),
- bNode *node,
- bNodeExecData *UNUSED(execdata),
- bNodeStack **in,
- bNodeStack **out)
-{
- float vec1[3], vec2[3];
-
- nodestack_get_vec(vec1, SOCK_VECTOR, in[0]);
- nodestack_get_vec(vec2, SOCK_VECTOR, in[1]);
-
- if (node->custom1 == 0) { /* Add */
- out[0]->vec[0] = vec1[0] + vec2[0];
- out[0]->vec[1] = vec1[1] + vec2[1];
- out[0]->vec[2] = vec1[2] + vec2[2];
-
- out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[1]) + fabsf(out[0]->vec[2])) /
- 3.0f;
- }
- else if (node->custom1 == 1) { /* Subtract */
- out[0]->vec[0] = vec1[0] - vec2[0];
- out[0]->vec[1] = vec1[1] - vec2[1];
- out[0]->vec[2] = vec1[2] - vec2[2];
-
- out[1]->vec[0] = (fabsf(out[0]->vec[0]) + fabsf(out[0]->vec[1]) + fabsf(out[0]->vec[2])) /
- 3.0f;
- }
- else if (node->custom1 == 2) { /* Average */
- out[0]->vec[0] = vec1[0] + vec2[0];
- out[0]->vec[1] = vec1[1] + vec2[1];
- out[0]->vec[2] = vec1[2] + vec2[2];
-
- out[1]->vec[0] = normalize_v3(out[0]->vec);
- }
- else if (node->custom1 == 3) { /* Dot product */
- out[1]->vec[0] = (vec1[0] * vec2[0]) + (vec1[1] * vec2[1]) + (vec1[2] * vec2[2]);
- }
- else if (node->custom1 == 4) { /* Cross product */
- out[0]->vec[0] = (vec1[1] * vec2[2]) - (vec1[2] * vec2[1]);
- out[0]->vec[1] = (vec1[2] * vec2[0]) - (vec1[0] * vec2[2]);
- out[0]->vec[2] = (vec1[0] * vec2[1]) - (vec1[1] * vec2[0]);
-
- out[1]->vec[0] = normalize_v3(out[0]->vec);
- }
- else if (node->custom1 == 5) { /* Normalize */
- /* This one only takes one input, so we've got to choose. */
- if (in[0]->hasinput || !in[1]->hasinput) {
- out[0]->vec[0] = vec1[0];
- out[0]->vec[1] = vec1[1];
- out[0]->vec[2] = vec1[2];
- }
- else {
- out[0]->vec[0] = vec2[0];
- out[0]->vec[1] = vec2[1];
- out[0]->vec[2] = vec2[2];
- }
-
- out[1]->vec[0] = normalize_v3(out[0]->vec);
- }
-}
-
-static int gpu_shader_vect_math(GPUMaterial *mat,
- bNode *node,
- bNodeExecData *UNUSED(execdata),
- GPUNodeStack *in,
- GPUNodeStack *out)
-{
- static const char *names[] = {
- "vec_math_add",
- "vec_math_sub",
- "vec_math_average",
- "vec_math_dot",
- "vec_math_cross",
- "vec_math_normalize",
- };
-
- switch (node->custom1) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- GPU_stack_link(mat, node, names[node->custom1], in, out);
- break;
- case 5:
- if (in[0].hasinput || !in[1].hasinput) {
- /* use only first item and terminator */
- GPUNodeStack tmp_in[2];
- memcpy(&tmp_in[0], &in[0], sizeof(GPUNodeStack));
- memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
- GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
- }
- else {
- /* use only second item and terminator */
- GPUNodeStack tmp_in[2];
- memcpy(&tmp_in[0], &in[1], sizeof(GPUNodeStack));
- memcpy(&tmp_in[1], &in[2], sizeof(GPUNodeStack));
- GPU_stack_link(mat, node, names[node->custom1], tmp_in, out);
- }
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-void register_node_type_sh_vect_math(void)
-{
- static bNodeType ntype;
-
- sh_node_type_base(&ntype, SH_NODE_VECT_MATH, "Vector Math", NODE_CLASS_CONVERTOR, 0);
- node_type_socket_templates(&ntype, sh_node_vect_math_in, sh_node_vect_math_out);
- node_type_label(&ntype, node_vect_math_label);
- node_type_storage(&ntype, "", NULL, NULL);
- node_type_exec(&ntype, NULL, NULL, node_shader_exec_vect_math);
- node_type_gpu(&ntype, gpu_shader_vect_math);
-
- nodeRegisterType(&ntype);
-}
diff --git a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c b/source/blender/nodes/shader/nodes/node_shader_vectTransform.c
index fe0e7b1d638..563ef89162b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_vectTransform.c
+++ b/source/blender/nodes/shader/nodes/node_shader_vectTransform.c
@@ -132,7 +132,7 @@ static int gpu_shader_vect_transform(GPUMaterial *mat,
}
if (nodeprop->type == SHD_VECT_TRANSFORM_TYPE_NORMAL) {
- GPU_link(mat, "vect_normalize", out[0].link, &out[0].link);
+ GPU_link(mat, "vector_normalize", out[0].link, &out[0].link);
}
return true;
diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.c b/source/blender/nodes/shader/nodes/node_shader_vector_math.c
new file mode 100644
index 00000000000..03de83655b5
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.c
@@ -0,0 +1,113 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup shdnodes
+ */
+
+#include "node_shader_util.h"
+
+/* **************** VECTOR MATH ******************** */
+static bNodeSocketTemplate sh_node_vector_math_in[] = {
+ {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
+ {SOCK_VECTOR, 1, N_("Vector"), 0.0f, 0.0f, 0.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
+ {SOCK_FLOAT, 1, N_("Scale"), 1.0f, 1.0f, 1.0f, 1.0f, -10000.0f, 10000.0f, PROP_NONE},
+ {-1, 0, ""}};
+
+static bNodeSocketTemplate sh_node_vector_math_out[] = {
+ {SOCK_VECTOR, 0, N_("Vector")}, {SOCK_FLOAT, 0, N_("Value")}, {-1, 0, ""}};
+
+static int gpu_shader_vector_math(GPUMaterial *mat,
+ bNode *node,
+ bNodeExecData *UNUSED(execdata),
+ GPUNodeStack *in,
+ GPUNodeStack *out)
+{
+ static const char *names[] = {
+ [NODE_VECTOR_MATH_ADD] = "vector_math_add",
+ [NODE_VECTOR_MATH_SUBTRACT] = "vector_math_subtract",
+ [NODE_VECTOR_MATH_MULTIPLY] = "vector_math_multiply",
+ [NODE_VECTOR_MATH_DIVIDE] = "vector_math_divide",
+
+ [NODE_VECTOR_MATH_CROSS_PRODUCT] = "vector_math_cross",
+ [NODE_VECTOR_MATH_PROJECT] = "vector_math_project",
+ [NODE_VECTOR_MATH_REFLECT] = "vector_math_reflect",
+ [NODE_VECTOR_MATH_DOT_PRODUCT] = "vector_math_dot",
+
+ [NODE_VECTOR_MATH_DISTANCE] = "vector_math_distance",
+ [NODE_VECTOR_MATH_LENGTH] = "vector_math_length",
+ [NODE_VECTOR_MATH_SCALE] = "vector_math_scale",
+ [NODE_VECTOR_MATH_NORMALIZE] = "vector_math_normalize",
+
+ [NODE_VECTOR_MATH_SNAP] = "vector_math_snap",
+ [NODE_VECTOR_MATH_FLOOR] = "vector_math_floor",
+ [NODE_VECTOR_MATH_CEIL] = "vector_math_ceil",
+ [NODE_VECTOR_MATH_MODULO] = "vector_math_modulo",
+ [NODE_VECTOR_MATH_FRACTION] = "vector_math_fraction",
+ [NODE_VECTOR_MATH_ABSOLUTE] = "vector_math_absolute",
+ [NODE_VECTOR_MATH_MINIMUM] = "vector_math_minimum",
+ [NODE_VECTOR_MATH_MAXIMUM] = "vector_math_maximum",
+ };
+
+ GPU_stack_link(mat, node, names[node->custom1], in, out);
+ return true;
+}
+
+static void node_shader_update_vector_math(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ bNodeSocket *sockB = BLI_findlink(&node->inputs, 1);
+ bNodeSocket *sockScale = nodeFindSocket(node, SOCK_IN, "Scale");
+
+ bNodeSocket *sockVector = nodeFindSocket(node, SOCK_OUT, "Vector");
+ bNodeSocket *sockValue = nodeFindSocket(node, SOCK_OUT, "Value");
+
+ nodeSetSocketAvailability(sockB,
+ !ELEM(node->custom1,
+ NODE_VECTOR_MATH_CEIL,
+ NODE_VECTOR_MATH_SCALE,
+ NODE_VECTOR_MATH_FLOOR,
+ NODE_VECTOR_MATH_LENGTH,
+ NODE_VECTOR_MATH_ABSOLUTE,
+ NODE_VECTOR_MATH_FRACTION,
+ NODE_VECTOR_MATH_NORMALIZE));
+ nodeSetSocketAvailability(sockScale, node->custom1 == NODE_VECTOR_MATH_SCALE);
+ nodeSetSocketAvailability(sockVector,
+ !ELEM(node->custom1,
+ NODE_VECTOR_MATH_LENGTH,
+ NODE_VECTOR_MATH_DISTANCE,
+ NODE_VECTOR_MATH_DOT_PRODUCT));
+ nodeSetSocketAvailability(sockValue,
+ ELEM(node->custom1,
+ NODE_VECTOR_MATH_LENGTH,
+ NODE_VECTOR_MATH_DISTANCE,
+ NODE_VECTOR_MATH_DOT_PRODUCT));
+}
+
+void register_node_type_sh_vect_math(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_CONVERTOR, 0);
+ node_type_socket_templates(&ntype, sh_node_vector_math_in, sh_node_vector_math_out);
+ node_type_label(&ntype, node_vector_math_label);
+ node_type_gpu(&ntype, gpu_shader_vector_math);
+ node_type_update(&ntype, node_shader_update_vector_math);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/shader/nodes/node_shader_volume_info.c b/source/blender/nodes/shader/nodes/node_shader_volume_info.c
new file mode 100644
index 00000000000..98c44dd590b
--- /dev/null
+++ b/source/blender/nodes/shader/nodes/node_shader_volume_info.c
@@ -0,0 +1,56 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ */
+
+#include "../node_shader_util.h"
+
+static bNodeSocketTemplate sh_node_volume_info_out[] = {
+ {SOCK_RGBA, 0, N_("Color")},
+ {SOCK_FLOAT, 0, N_("Density")},
+ {SOCK_FLOAT, 0, N_("Flame")},
+ {SOCK_FLOAT, 0, N_("Temperature")},
+ {-1, 0, ""},
+};
+
+static int node_shader_gpu_volume_info(GPUMaterial *mat,
+ bNode *node,
+ bNodeExecData *UNUSED(execdata),
+ GPUNodeStack *in,
+ GPUNodeStack *out)
+{
+
+ return GPU_stack_link(mat,
+ node,
+ "node_volume_info",
+ in,
+ out,
+ GPU_builtin(GPU_VOLUME_DENSITY),
+ GPU_builtin(GPU_VOLUME_FLAME),
+ GPU_builtin(GPU_VOLUME_TEMPERATURE));
+}
+
+void register_node_type_sh_volume_info(void)
+{
+ static bNodeType ntype;
+
+ sh_node_type_base(&ntype, SH_NODE_VOLUME_INFO, "Volume Info", NODE_CLASS_INPUT, 0);
+ node_type_socket_templates(&ntype, NULL, sh_node_volume_info_out);
+ node_type_gpu(&ntype, node_shader_gpu_volume_info);
+
+ nodeRegisterType(&ntype);
+}
diff --git a/source/blender/nodes/texture/nodes/node_texture_math.c b/source/blender/nodes/texture/nodes/node_texture_math.c
index 2eb32e0addc..b1d67a5a953 100644
--- a/source/blender/nodes/texture/nodes/node_texture_math.c
+++ b/source/blender/nodes/texture/nodes/node_texture_math.c
@@ -46,10 +46,10 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
case NODE_MATH_ADD:
*out = in0 + in1;
break;
- case NODE_MATH_SUB:
+ case NODE_MATH_SUBTRACT:
*out = in0 - in1;
break;
- case NODE_MATH_MUL:
+ case NODE_MATH_MULTIPLY:
*out = in0 * in1;
break;
case NODE_MATH_DIVIDE: {
@@ -62,19 +62,19 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
break;
}
- case NODE_MATH_SIN: {
+ case NODE_MATH_SINE: {
*out = sinf(in0);
break;
}
- case NODE_MATH_COS: {
+ case NODE_MATH_COSINE: {
*out = cosf(in0);
break;
}
- case NODE_MATH_TAN: {
+ case NODE_MATH_TANGENT: {
*out = tanf(in0);
break;
}
- case NODE_MATH_ASIN: {
+ case NODE_MATH_ARCSINE: {
/* Can't do the impossible... */
if (in0 <= 1 && in0 >= -1) {
*out = asinf(in0);
@@ -84,7 +84,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
break;
}
- case NODE_MATH_ACOS: {
+ case NODE_MATH_ARCCOSINE: {
/* Can't do the impossible... */
if (in0 <= 1 && in0 >= -1) {
*out = acosf(in0);
@@ -94,11 +94,11 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
break;
}
- case NODE_MATH_ATAN: {
+ case NODE_MATH_ARCTANGENT: {
*out = atan(in0);
break;
}
- case NODE_MATH_POW: {
+ case NODE_MATH_POWER: {
/* Only raise negative numbers by full integers */
if (in0 >= 0) {
out[0] = pow(in0, in1);
@@ -114,7 +114,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
break;
}
- case NODE_MATH_LOG: {
+ case NODE_MATH_LOGARITHM: {
/* Don't want any imaginary numbers... */
if (in0 > 0 && in1 > 0) {
*out = log(in0) / log(in1);
@@ -124,7 +124,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
break;
}
- case NODE_MATH_MIN: {
+ case NODE_MATH_MINIMUM: {
if (in0 < in1) {
*out = in0;
}
@@ -133,7 +133,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
}
break;
}
- case NODE_MATH_MAX: {
+ case NODE_MATH_MAXIMUM: {
if (in0 > in1) {
*out = in0;
}
@@ -147,7 +147,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
break;
}
- case NODE_MATH_LESS: {
+ case NODE_MATH_LESS_THAN: {
if (in0 < in1) {
*out = 1.0f;
}
@@ -157,7 +157,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
break;
}
- case NODE_MATH_GREATER: {
+ case NODE_MATH_GREATER_THAN: {
if (in0 > in1) {
*out = 1.0f;
}
@@ -167,7 +167,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
break;
}
- case NODE_MATH_MOD: {
+ case NODE_MATH_MODULO: {
if (in1 == 0.0f) {
*out = 0.0f;
}
@@ -177,12 +177,12 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
break;
}
- case NODE_MATH_ABS: {
+ case NODE_MATH_ABSOLUTE: {
*out = fabsf(in0);
break;
}
- case NODE_MATH_ATAN2: {
+ case NODE_MATH_ARCTAN2: {
*out = atan2(in0, in1);
break;
}
@@ -197,7 +197,7 @@ static void valuefn(float *out, TexParams *p, bNode *node, bNodeStack **in, shor
break;
}
- case NODE_MATH_FRACT: {
+ case NODE_MATH_FRACTION: {
*out = in0 - floorf(in0);
break;
}
diff --git a/source/blender/physics/BPH_mass_spring.h b/source/blender/physics/BPH_mass_spring.h
index 9666f9ba9ed..c0ceff4d8cf 100644
--- a/source/blender/physics/BPH_mass_spring.h
+++ b/source/blender/physics/BPH_mass_spring.h
@@ -33,7 +33,6 @@ struct Depsgraph;
struct Implicit_Data;
struct ListBase;
struct Object;
-struct VoxelData;
typedef enum eMassSpringSolverStatus {
BPH_SOLVER_SUCCESS = (1 << 0),
diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp
index 95c16c2f033..07cb3370eec 100644
--- a/source/blender/physics/intern/BPH_mass_spring.cpp
+++ b/source/blender/physics/intern/BPH_mass_spring.cpp
@@ -393,7 +393,7 @@ BLI_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s)
if (s->type & CLOTH_SPRING_TYPE_SEWING) {
/* TODO: verify, half verified (couldn't see error)
* sewing springs usually have a large distance at first so clamp the force so we don't get
- * tunnelling through collision objects. */
+ * tunneling through collision objects. */
BPH_mass_spring_force_spring_linear(data,
s->ij,
s->kl,
diff --git a/source/blender/physics/intern/implicit.h b/source/blender/physics/intern/implicit.h
index a88a5785fee..32416fa01ab 100644
--- a/source/blender/physics/intern/implicit.h
+++ b/source/blender/physics/intern/implicit.h
@@ -186,8 +186,6 @@ bool BPH_mass_spring_force_spring_goal(struct Implicit_Data *data,
struct HairGrid;
-struct VoxelData;
-
#define MAX_HAIR_GRID_RES 256
struct HairGrid *BPH_hair_volume_create_vertex_grid(float cellsize,
diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.c b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
index 0aa01ddb594..2e15c1d9ce0 100644
--- a/source/blender/python/bmesh/bmesh_py_types_meshdata.c
+++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.c
@@ -20,8 +20,8 @@
/** \file
* \ingroup pybmesh
*
- * This file defines customdata types which can't be accessed as primitive
- * python types such as MDeformVert, MLoopUV, MTexPoly
+ * This file defines custom-data types which can't be accessed as primitive
+ * python types such as #MDeformVert, #MLoopUV.
*/
#include <Python.h>
@@ -515,8 +515,8 @@ static PySequenceMethods bpy_bmdeformvert_as_sequence = {
NULL, /* sq_concat */
NULL, /* sq_repeat */
- /* note: if this is set PySequence_Check() returns True,
- * but in this case we dont want to be treated as a seq */
+ /* Note: if this is set #PySequence_Check() returns True,
+ * but in this case we don't want to be treated as a seq. */
NULL, /* sq_item */
NULL, /* sq_slice */
diff --git a/source/blender/python/intern/CMakeLists.txt b/source/blender/python/intern/CMakeLists.txt
index fc945562c98..a5f71e92438 100644
--- a/source/blender/python/intern/CMakeLists.txt
+++ b/source/blender/python/intern/CMakeLists.txt
@@ -231,6 +231,10 @@ if(WITH_OPENAL)
add_definitions(-DWITH_OPENAL)
endif()
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+endif()
+
if(WITH_SDL)
list(APPEND INC_SYS
${SDL_INCLUDE_DIR}
diff --git a/source/blender/python/intern/bpy_app_build_options.c b/source/blender/python/intern/bpy_app_build_options.c
index a841e974e85..afb2f6b3636 100644
--- a/source/blender/python/intern/bpy_app_build_options.c
+++ b/source/blender/python/intern/bpy_app_build_options.c
@@ -46,6 +46,7 @@ static PyStructSequence_Field app_builtopts_info_fields[] = {
{(char *)"audaspace", NULL},
{(char *)"international", NULL},
{(char *)"openal", NULL},
+ {(char *)"opensubdiv", NULL},
{(char *)"sdl", NULL},
{(char *)"sdl_dynload", NULL},
{(char *)"jack", NULL},
@@ -190,6 +191,12 @@ static PyObject *make_builtopts_info(void)
SetObjIncref(Py_False);
#endif
+#ifdef WITH_OPENSUBDIV
+ SetObjIncref(Py_True);
+#else
+ SetObjIncref(Py_False);
+#endif
+
#ifdef WITH_SDL
SetObjIncref(Py_True);
#else
diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c
index a48cd742448..3c1dbfba72e 100644
--- a/source/blender/python/intern/bpy_app_translations.c
+++ b/source/blender/python/intern/bpy_app_translations.c
@@ -890,7 +890,7 @@ PyObject *BPY_app_translations_struct(void)
void BPY_app_translations_end(void)
{
- /* Incase the object remains in a module's namespace, see T44127. */
+ /* In case the object remains in a module's name-space, see T44127. */
#ifdef WITH_INTERNATIONAL
_clear_translations_cache();
#endif
diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c
index 71bc01d6b98..a73e4034ca6 100644
--- a/source/blender/python/intern/bpy_interface.c
+++ b/source/blender/python/intern/bpy_interface.c
@@ -808,7 +808,7 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
ptr = &(((BPy_StructRNA *)item)->ptr);
// result->ptr = ((BPy_StructRNA *)item)->ptr;
- CTX_data_pointer_set(result, ptr->id.data, ptr->type, ptr->data);
+ CTX_data_pointer_set(result, ptr->owner_id, ptr->type, ptr->data);
CTX_data_type_set(result, CTX_DATA_TYPE_POINTER);
done = true;
}
@@ -834,7 +834,7 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult *
BLI_addtail(&result->list, link);
#endif
ptr = &(((BPy_StructRNA *)list_item)->ptr);
- CTX_data_list_add(result, ptr->id.data, ptr->type, ptr->data);
+ CTX_data_list_add(result, ptr->owner_id, ptr->type, ptr->data);
}
else {
CLOG_INFO(BPY_LOG_CONTEXT,
diff --git a/source/blender/python/intern/bpy_msgbus.c b/source/blender/python/intern/bpy_msgbus.c
index 9db4201c252..630a0392dbd 100644
--- a/source/blender/python/intern/bpy_msgbus.c
+++ b/source/blender/python/intern/bpy_msgbus.c
@@ -269,7 +269,7 @@ static PyObject *bpy_msgbus_subscribe_rna(PyObject *UNUSED(self), PyObject *args
/* Note: we may want to have a way to pass this in. */
bContext *C = (bContext *)BPy_GetContext();
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- wmMsgParams_RNA msg_key_params = {{{0}}};
+ wmMsgParams_RNA msg_key_params = {{0}};
wmMsgSubscribeValue msg_val_params = {0};
@@ -342,7 +342,7 @@ static PyObject *bpy_msgbus_publish_rna(PyObject *UNUSED(self), PyObject *args,
/* Note: we may want to have a way to pass this in. */
bContext *C = (bContext *)BPy_GetContext();
struct wmMsgBus *mbus = CTX_wm_message_bus(C);
- wmMsgParams_RNA msg_key_params = {{{0}}};
+ wmMsgParams_RNA msg_key_params = {{0}};
if (py_msgbus_rna_key_from_py(py_sub, &msg_key_params, error_prefix) == -1) {
return NULL;
diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c
index 8f2f08c7c37..2e88a2a5b06 100644
--- a/source/blender/python/intern/bpy_operator_wrap.c
+++ b/source/blender/python/intern/bpy_operator_wrap.c
@@ -58,7 +58,7 @@ static void operator_properties_init(wmOperatorType *ot)
/* set the default property: ot->prop */
{
/* Picky developers will notice that 'bl_property' won't work with inheritance
- * get direct from the dict to avoid raising a load of attribute errors (yes this isnt ideal)
+ * get direct from the dict to avoid raising a load of attribute errors (yes this isn't ideal)
* - campbell. */
PyObject *py_class_dict = py_class->tp_dict;
PyObject *bl_property = PyDict_GetItem(py_class_dict, bpy_intern_str_bl_property);
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 9a8d8c5ec21..12005b92388 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -139,7 +139,7 @@ static void id_release_gc(struct ID *id)
if (PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) ||
PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) {
BPy_DummyPointerRNA *ob_ptr = (BPy_DummyPointerRNA *)ob;
- if (ob_ptr->ptr.id.data == id) {
+ if (ob_ptr->ptr.owner_id == id) {
pyrna_invalidate(ob_ptr);
// printf("freeing: %p %s, %.200s\n", (void *)ob, id->name, Py_TYPE(ob)->tp_name);
// i++;
@@ -308,7 +308,7 @@ static bool rna_disallow_writes = false;
static bool rna_id_write_error(PointerRNA *ptr, PyObject *key)
{
- ID *id = ptr->id.data;
+ ID *id = ptr->owner_id;
if (id) {
const short idcode = GS(id->name);
/* May need more ID types added here. */
@@ -907,7 +907,7 @@ static PyObject *pyrna_struct_str(BPy_StructRNA *self)
static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
{
- ID *id = self->ptr.id.data;
+ ID *id = self->ptr.owner_id;
PyObject *tmp_str;
PyObject *ret;
@@ -918,21 +918,21 @@ static PyObject *pyrna_struct_repr(BPy_StructRNA *self)
tmp_str = PyUnicode_FromString(id->name + 2);
- if (RNA_struct_is_ID(self->ptr.type)) {
+ if (RNA_struct_is_ID(self->ptr.type) && (id->flag & LIB_PRIVATE_DATA) == 0) {
ret = PyUnicode_FromFormat(
"bpy.data.%s[%R]", BKE_idcode_to_name_plural(GS(id->name)), tmp_str);
}
else {
const char *path;
- path = RNA_path_from_ID_to_struct(&self->ptr);
+ ID *real_id = NULL;
+ path = RNA_path_from_real_ID_to_struct(G_MAIN, &self->ptr, &real_id);
if (path) {
- if (GS(id->name) == ID_NT) { /* Nodetree paths are not accurate. */
- ret = PyUnicode_FromFormat("bpy.data...%s", path);
- }
- else {
- ret = PyUnicode_FromFormat(
- "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(id->name)), tmp_str, path);
+ if (real_id != id) {
+ Py_DECREF(tmp_str);
+ tmp_str = PyUnicode_FromString(real_id->name + 2);
}
+ ret = PyUnicode_FromFormat(
+ "bpy.data.%s[%R].%s", BKE_idcode_to_name_plural(GS(real_id->name)), tmp_str, path);
MEM_freeN((void *)path);
}
@@ -1019,7 +1019,7 @@ static PyObject *pyrna_prop_str(BPy_PropertyRNA *self)
static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim, const int index)
{
- ID *id = self->ptr.id.data;
+ ID *id = self->ptr.owner_id;
PyObject *tmp_str;
PyObject *ret;
const char *path;
@@ -1033,20 +1033,23 @@ static PyObject *pyrna_prop_repr_ex(BPy_PropertyRNA *self, const int index_dim,
tmp_str = PyUnicode_FromString(id->name + 2);
- path = RNA_path_from_ID_to_property_index(&self->ptr, self->prop, index_dim, index);
+ /* Note that using G_MAIN is absolutely not ideal, but we have no access to actual Main DB from
+ * here. */
+ ID *real_id = NULL;
+ path = RNA_path_from_real_ID_to_property_index(
+ G_MAIN, &self->ptr, self->prop, index_dim, index, &real_id);
if (path) {
- const char *data_delim = (path[0] == '[') ? "" : ".";
- if (GS(id->name) == ID_NT) { /* Nodetree paths are not accurate. */
- ret = PyUnicode_FromFormat("bpy.data...%s", path);
- }
- else {
- ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s",
- BKE_idcode_to_name_plural(GS(id->name)),
- tmp_str,
- data_delim,
- path);
+ if (real_id != id) {
+ Py_DECREF(tmp_str);
+ tmp_str = PyUnicode_FromString(real_id->name + 2);
}
+ const char *data_delim = (path[0] == '[') ? "" : ".";
+ ret = PyUnicode_FromFormat("bpy.data.%s[%R]%s%s",
+ BKE_idcode_to_name_plural(GS(real_id->name)),
+ tmp_str,
+ data_delim,
+ path);
MEM_freeN((void *)path);
}
@@ -1982,7 +1985,7 @@ static int pyrna_py_to_prop(
return -1;
}
else if ((value != Py_None) && ((flag & PROP_ID_SELF_CHECK) &&
- ptr->id.data == ((BPy_StructRNA *)value)->ptr.id.data)) {
+ ptr->owner_id == ((BPy_StructRNA *)value)->ptr.owner_id)) {
PyErr_Format(PyExc_TypeError,
"%.200s %.200s.%.200s ID type does not support assignment to itself",
error_prefix,
@@ -3447,7 +3450,7 @@ static PyObject *pyrna_struct_subscript(BPy_StructRNA *self, PyObject *key)
return NULL;
}
- return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group);
+ return BPy_IDGroup_WrapData(self->ptr.owner_id, idprop, group);
}
static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObject *value)
@@ -3543,7 +3546,7 @@ static PyObject *pyrna_struct_items(BPy_PropertyRNA *self)
return PyList_New(0);
}
- return BPy_Wrap_GetItems(self->ptr.id.data, group);
+ return BPy_Wrap_GetItems(self->ptr.owner_id, group);
}
PyDoc_STRVAR(pyrna_struct_values_doc,
@@ -3571,7 +3574,7 @@ static PyObject *pyrna_struct_values(BPy_PropertyRNA *self)
return PyList_New(0);
}
- return BPy_Wrap_GetValues(self->ptr.id.data, group);
+ return BPy_Wrap_GetValues(self->ptr.owner_id, group);
}
PyDoc_STRVAR(pyrna_struct_is_property_set_doc,
@@ -4708,9 +4711,9 @@ PyDoc_STRVAR(pyrna_struct_get_id_data_doc,
static PyObject *pyrna_struct_get_id_data(BPy_DummyPointerRNA *self)
{
/* Used for struct and pointer since both have a ptr. */
- if (self->ptr.id.data) {
+ if (self->ptr.owner_id) {
PointerRNA id_ptr;
- RNA_id_pointer_create((ID *)self->ptr.id.data, &id_ptr);
+ RNA_id_pointer_create((ID *)self->ptr.owner_id, &id_ptr);
return pyrna_struct_CreatePyObject(&id_ptr);
}
@@ -4894,7 +4897,7 @@ static PyObject *pyrna_struct_get(BPy_StructRNA *self, PyObject *args)
idprop = IDP_GetPropertyFromGroup(group, key);
if (idprop) {
- return BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group);
+ return BPy_IDGroup_WrapData(self->ptr.owner_id, idprop, group);
}
}
@@ -4937,7 +4940,7 @@ static PyObject *pyrna_struct_pop(BPy_StructRNA *self, PyObject *args)
idprop = IDP_GetPropertyFromGroup(group, key);
if (idprop) {
- PyObject *ret = BPy_IDGroup_WrapData(self->ptr.id.data, idprop, group);
+ PyObject *ret = BPy_IDGroup_WrapData(self->ptr.owner_id, idprop, group);
IDP_RemoveFromGroup(group, idprop);
return ret;
}
@@ -5787,7 +5790,7 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
* and will break if a function returns a pointer from
* another ID block, watch this! - it should at least be
* easy to debug since they are all ID's */
- RNA_pointer_create(ptr->id.data, ptype, *(void **)data, &newptr);
+ RNA_pointer_create(ptr->owner_id, ptype, *(void **)data, &newptr);
}
}
@@ -5903,7 +5906,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject
/* include the ID pointer for pyrna_param_to_py() so we can include the
* ID pointer on return values, this only works when returned values have
* the same ID as the functions. */
- RNA_pointer_create(self_ptr->id.data, &RNA_Function, self_func, &funcptr);
+ RNA_pointer_create(self_ptr->owner_id, &RNA_Function, self_func, &funcptr);
pyargs_len = PyTuple_GET_SIZE(args);
pykw_len = kw ? PyDict_Size(kw) : 0;
@@ -6987,7 +6990,7 @@ static void pyrna_subtype_set_rna(PyObject *newclass, StructRNA *srna)
/* Add staticmethods and classmethods. */
{
- const PointerRNA func_ptr = {{NULL}, srna, NULL};
+ const PointerRNA func_ptr = {NULL, srna, NULL};
const ListBase *lb;
Link *link;
@@ -7285,8 +7288,8 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr)
// PyC_ObSpit("NewStructRNA: ", (PyObject *)pyrna);
#ifdef USE_PYRNA_INVALIDATE_WEAKREF
- if (ptr->id.data) {
- id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna);
+ if (ptr->owner_id) {
+ id_weakref_pool_add(ptr->owner_id, (BPy_DummyPointerRNA *)pyrna);
}
#endif
return (PyObject *)pyrna;
@@ -7334,8 +7337,8 @@ PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop)
pyrna->prop = prop;
#ifdef USE_PYRNA_INVALIDATE_WEAKREF
- if (ptr->id.data) {
- id_weakref_pool_add(ptr->id.data, (BPy_DummyPointerRNA *)pyrna);
+ if (ptr->owner_id) {
+ id_weakref_pool_add(ptr->owner_id, (BPy_DummyPointerRNA *)pyrna);
}
#endif
@@ -7358,7 +7361,7 @@ PyObject *pyrna_id_CreatePyObject(ID *id)
bool pyrna_id_FromPyObject(PyObject *obj, ID **id)
{
if (pyrna_id_CheckPyObject(obj)) {
- *id = ((BPy_StructRNA *)obj)->ptr.id.data;
+ *id = ((BPy_StructRNA *)obj)->ptr.owner_id;
return true;
}
else {
@@ -8557,9 +8560,10 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class
}
if (PyDict_GetItem(((PyTypeObject *)py_class)->tp_dict, bpy_intern_str_bl_rna)) {
- PyErr_SetString(PyExc_ValueError,
- "register_class(...): "
- "already registered as a subclass");
+ PyErr_Format(PyExc_ValueError,
+ "register_class(...): "
+ "already registered as a subclass '%.200s'",
+ ((PyTypeObject *)py_class)->tp_name);
return NULL;
}
diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c
index 7a3499d0295..5e535d0e3ce 100644
--- a/source/blender/python/intern/bpy_rna_anim.c
+++ b/source/blender/python/intern/bpy_rna_anim.c
@@ -88,7 +88,7 @@ static int pyrna_struct_anim_args_parse_ex(PointerRNA *ptr,
path);
return -1;
}
- else if (ptr->id.data != r_ptr.id.data) {
+ else if (ptr->owner_id != r_ptr.owner_id) {
PyErr_Format(PyExc_ValueError, "%.200s path spans ID blocks", error_prefix, path);
return -1;
}
@@ -370,7 +370,7 @@ PyObject *pyrna_struct_keyframe_insert(BPy_StructRNA *self, PyObject *args, PyOb
return PyBool_FromLong(result);
}
else {
- ID *id = self->ptr.id.data;
+ ID *id = self->ptr.owner_id;
ReportList reports;
short result;
@@ -451,7 +451,7 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb
}
if (prop) {
- ID *id = ptr.id.data;
+ ID *id = ptr.owner_id;
NlaStrip *strip = (NlaStrip *)ptr.data;
FCurve *fcu = list_find_fcurve(&strip->fcurves, RNA_property_identifier(prop), index);
@@ -502,7 +502,7 @@ PyObject *pyrna_struct_keyframe_delete(BPy_StructRNA *self, PyObject *args, PyOb
BKE_reports_init(&reports, RPT_STORE);
result = delete_keyframe(
- G.main, &reports, (ID *)self->ptr.id.data, NULL, group_name, path_full, index, cfra, 0);
+ G.main, &reports, (ID *)self->ptr.owner_id, NULL, group_name, path_full, index, cfra, 0);
MEM_freeN((void *)path_full);
if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) {
@@ -548,7 +548,7 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
BKE_reports_init(&reports, RPT_STORE);
result = ANIM_add_driver(&reports,
- (ID *)self->ptr.id.data,
+ (ID *)self->ptr.owner_id,
path_full,
index,
CREATEDRIVER_WITH_FMODIFIER,
@@ -559,7 +559,7 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
}
if (result) {
- ID *id = self->ptr.id.data;
+ ID *id = self->ptr.owner_id;
AnimData *adt = BKE_animdata_from_id(id);
FCurve *fcu;
@@ -629,7 +629,7 @@ PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
BKE_reports_init(&reports, RPT_STORE);
- result = ANIM_remove_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0);
+ result = ANIM_remove_driver(&reports, (ID *)self->ptr.owner_id, path_full, index, 0);
if (path != path_full) {
MEM_freeN((void *)path_full);
diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c
index e9e8d05aa74..a8d8252b231 100644
--- a/source/blender/python/intern/bpy_rna_driver.c
+++ b/source/blender/python/intern/bpy_rna_driver.c
@@ -91,7 +91,7 @@ bool pyrna_driver_is_equal_anim_rna(const PathResolvedRNA *anim_rna, const PyObj
const PointerRNA *ptr_a = &anim_rna->ptr;
const PointerRNA *ptr_b = &(((const BPy_StructRNA *)py_anim_rna)->ptr);
- if ((ptr_a->id.data == ptr_b->id.data) && (ptr_a->type == ptr_b->type) &&
+ if ((ptr_a->owner_id == ptr_b->owner_id) && (ptr_a->type == ptr_b->type) &&
(ptr_a->data == ptr_b->data)) {
return true;
}
diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c
index 23fd65319a6..267971408bf 100644
--- a/source/blender/python/mathutils/mathutils_Quaternion.c
+++ b/source/blender/python/mathutils/mathutils_Quaternion.c
@@ -1015,7 +1015,7 @@ static PyObject *Quaternion_matmul(PyObject *q1, PyObject *q2)
return NULL;
}
/*------------------------obj @= obj------------------------------
- * inplace quaternion multiplication */
+ * in-place quaternion multiplication */
static PyObject *Quaternion_imatmul(PyObject *q1, PyObject *q2)
{
float quat[QUAT_SIZE];
diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c
index 490a1d9dd76..aa7cbadde14 100644
--- a/source/blender/python/mathutils/mathutils_Vector.c
+++ b/source/blender/python/mathutils/mathutils_Vector.c
@@ -786,10 +786,8 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
return NULL;
}
- /*
- * flip vector around, since vectoquat expect a vector from target to tracking object
- * and the python function expects the inverse (a vector to the target).
- */
+ /* Flip vector around, since #vec_to_quat expect a vector from target to tracking object
+ * and the python function expects the inverse (a vector to the target). */
negate_v3_v3(vec, self->vec);
vec_to_quat(quat, vec, track, up);
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index a6dded4ee8b..13d36e5af91 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -1213,7 +1213,7 @@ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject
PyObject *polyLine, *polyVec;
int i, len_polylines, len_polypoints, ls_error = 0;
- /* display listbase */
+ /* Display #ListBase. */
ListBase dispbase = {NULL, NULL};
DispList *dl;
float *fp; /*pointer to the array of malloced dl->verts to set the points from the vectors */
@@ -1299,7 +1299,7 @@ static PyObject *M_Geometry_tessellate_polygon(PyObject *UNUSED(self), PyObject
BKE_displist_fill(&dispbase, &dispbase, NULL, false);
/* The faces are stored in a new DisplayList
- * that's added to the head of the listbase */
+ * that's added to the head of the #ListBase. */
dl = dispbase.first;
tri_list = PyList_New(dl->parts);
@@ -1510,7 +1510,7 @@ static PyObject *M_Geometry_convex_hull_2d(PyObject *UNUSED(self), PyObject *poi
/* Return a PyObject that is a list of lists, using the flattened list array
* to fill values, with start_table and len_table giving the start index
- * and length of the toplevel_len sublists
+ * and length of the toplevel_len sub-lists.
*/
static PyObject *list_of_lists_from_arrays(int *array,
int *start_table,
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index dee8dbfaa24..12e9123b5cb 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -33,7 +33,6 @@
struct BakePixel;
struct Depsgraph;
-struct IDProperty;
struct Main;
struct Object;
struct Render;
diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h
index 93b85b6b96a..dc18bac541f 100644
--- a/source/blender/render/extern/include/RE_pipeline.h
+++ b/source/blender/render/extern/include/RE_pipeline.h
@@ -28,11 +28,9 @@
#include "DNA_vec_types.h"
#include "DEG_depsgraph.h"
-struct Depsgraph;
struct Image;
struct ImageFormatData;
struct Main;
-struct NodeBlurData;
struct Object;
struct RenderData;
struct RenderResult;
@@ -41,7 +39,6 @@ struct Scene;
struct StampData;
struct ViewLayer;
struct bMovieHandle;
-struct bNodeTree;
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* this include is what is exposed of render to outside world */
@@ -256,7 +253,7 @@ void RE_SetView(struct Render *re, float mat[4][4]);
/* get current view and window transform */
void RE_GetViewPlane(struct Render *re, rctf *r_viewplane, rcti *r_disprect);
-/* set the render threads based on the commandline and autothreads setting */
+/* set the render threads based on the command-line and autothreads setting */
void RE_init_threadcount(Render *re);
bool RE_WriteRenderViewsImage(struct ReportList *reports,
diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h
index 6771eb53abd..bca3b749192 100644
--- a/source/blender/render/extern/include/RE_render_ext.h
+++ b/source/blender/render/extern/include/RE_render_ext.h
@@ -31,9 +31,6 @@
struct Depsgraph;
struct ImagePool;
struct MTex;
-struct Render;
-struct Scene;
-struct ViewLayer;
/* render_texture.c */
/* used by particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */
diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h
index c5e3575d1f9..792b2b7e071 100644
--- a/source/blender/render/extern/include/RE_shader_ext.h
+++ b/source/blender/render/extern/include/RE_shader_ext.h
@@ -41,10 +41,8 @@ typedef struct BakeImBufuserData {
} BakeImBufuserData;
/* node shaders... */
-struct ImBuf;
struct ImagePool;
struct MTex;
-struct Object;
struct Tex;
/* this one uses nodes */
diff --git a/source/blender/render/intern/source/bake_api.c b/source/blender/render/intern/source/bake_api.c
index c61c9b4dd7a..4e5a83555eb 100644
--- a/source/blender/render/intern/source/bake_api.c
+++ b/source/blender/render/intern/source/bake_api.c
@@ -700,7 +700,7 @@ void RE_bake_pixels_populate(Mesh *me,
}
else {
int uv_id = CustomData_get_named_layer(&me->ldata, CD_MLOOPUV, uv_layer);
- mloopuv = CustomData_get_layer_n(&me->ldata, CD_MTFACE, uv_id);
+ mloopuv = CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, uv_id);
}
if (mloopuv == NULL) {
diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c
index e9175d8d024..9672184cec8 100644
--- a/source/blender/render/intern/source/imagetexture.c
+++ b/source/blender/render/intern/source/imagetexture.c
@@ -267,7 +267,7 @@ int imagewrap(Tex *tex,
if (texres->nor) {
if (tex->imaflag & TEX_NORMALMAP) {
- /* qdn: normal from color
+ /* Normal from color:
* The invert of the red channel is to make
* the normal map compliant with the outside world.
* It needs to be done because in Blender
diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c
index 6284fa2d119..b4d0c2147f2 100644
--- a/source/blender/render/intern/source/pipeline.c
+++ b/source/blender/render/intern/source/pipeline.c
@@ -1992,8 +1992,8 @@ static int render_initialize_from_main(Render *re,
winx = (rd->size * rd->xsch) / 100;
winy = (rd->size * rd->ysch) / 100;
- /* We always render smaller part, inserting it in larger image is compositor bizz,
- * it uses disprect for it. */
+ /* We always render smaller part, inserting it in larger image is compositor business,
+ * it uses 'disprect' for it. */
if (scene->r.mode & R_BORDER) {
disprect.xmin = rd->border.xmin * winx;
disprect.xmax = rd->border.xmax * winx;
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index cf87afa2a34..c7b18adf9b1 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -53,19 +53,15 @@ struct PropertyRNA;
struct ScrArea;
struct ViewLayer;
struct bContext;
-struct bToolRef_Runtime;
struct rcti;
struct wmDrag;
struct wmDropBox;
struct wmEvent;
-struct wmEventHandler;
struct wmEventHandler_Keymap;
struct wmEventHandler_UI;
struct wmGenericUserData;
struct wmGesture;
struct wmJob;
-struct wmMsgSubscribeKey;
-struct wmMsgSubscribeValue;
struct wmOperator;
struct wmOperatorType;
struct wmPaintCursor;
@@ -162,7 +158,8 @@ enum {
WM_WINDOW_RENDER = 1,
WM_WINDOW_USERPREFS,
WM_WINDOW_DRIVERS,
- // WM_WINDOW_FILESEL // UNUSED
+ WM_WINDOW_INFO,
+ WM_WINDOW_FILESEL,
};
struct wmWindow *WM_window_open(struct bContext *C, const struct rcti *rect);
@@ -496,6 +493,8 @@ bool WM_operator_properties_checker_interval_test(const struct CheckerIntervalPa
#define WM_FILESEL_FILENAME (1 << 2)
#define WM_FILESEL_FILEPATH (1 << 3)
#define WM_FILESEL_FILES (1 << 4)
+/* Show the properties sidebar by default. */
+#define WM_FILESEL_SHOW_PROPS (1 << 5)
/* operator as a python command (resultuing string must be freed) */
char *WM_operator_pystring_ex(struct bContext *C,
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h
index 195822efd7e..7fdbf79248b 100644
--- a/source/blender/windowmanager/WM_types.h
+++ b/source/blender/windowmanager/WM_types.h
@@ -117,7 +117,6 @@ struct ID;
struct ImBuf;
struct bContext;
struct wmEvent;
-struct wmMsgBus;
struct wmOperator;
struct wmWindowManager;
diff --git a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
index f0771437518..00df6edef22 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_intern.h
@@ -22,8 +22,6 @@
#define __WM_GIZMO_INTERN_H__
struct BLI_Buffer;
-struct GHashIterator;
-struct GizmoGeomInfo;
struct wmGizmoMap;
struct wmKeyConfig;
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 f5ae5427ac7..094fdf3f514 100644
--- a/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c
+++ b/source/blender/windowmanager/gizmo/intern/wm_gizmo_target_props.c
@@ -84,6 +84,7 @@ void WM_gizmo_target_property_def_rna_ptr(wmGizmo *gz,
/* if gizmo evokes an operator we cannot use it for property manipulation */
BLI_assert(gz->op_data == NULL);
+ BLI_assert(prop != NULL);
gz_prop->type = gz_prop_type;
@@ -101,6 +102,9 @@ void WM_gizmo_target_property_def_rna(
{
const wmGizmoPropertyType *gz_prop_type = WM_gizmotype_target_property_find(gz->type, idname);
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+ if (prop == NULL) {
+ RNA_warning("%s: %s.%s not found", __func__, RNA_struct_identifier(ptr->type), propname);
+ }
WM_gizmo_target_property_def_rna_ptr(gz, gz_prop_type, ptr, prop, index);
}
diff --git a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h
index 242b0f6de80..58b58fa01d0 100644
--- a/source/blender/windowmanager/gizmo/wm_gizmo_fn.h
+++ b/source/blender/windowmanager/gizmo/wm_gizmo_fn.h
@@ -25,6 +25,8 @@
#include "BLI_compiler_attrs.h"
+struct wmMsgBus;
+
/* wmGizmoGroup */
typedef bool (*wmGizmoGroupFnPoll)(const struct bContext *,
struct wmGizmoGroupType *) ATTR_WARN_UNUSED_RESULT;
diff --git a/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h b/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h
index 33c0d305e59..cc9ccc5f4bb 100644
--- a/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h
+++ b/source/blender/windowmanager/gizmo/wm_gizmo_wmapi.h
@@ -31,11 +31,9 @@
#ifndef __WM_GIZMO_WMAPI_H__
#define __WM_GIZMO_WMAPI_H__
-struct wmEventHandler;
struct wmEventHandler_Gizmo;
struct wmEventHandler_Op;
struct wmGizmoMap;
-struct wmOperator;
struct wmOperatorType;
/* -------------------------------------------------------------------- */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 832bf1e9b6d..7192b25a7d5 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -2259,7 +2259,7 @@ static int wm_handler_operator_call(bContext *C,
if (ot && wm_operator_check_locked_interface(C, ot)) {
bool use_last_properties = true;
- PointerRNA tool_properties = {{0}};
+ PointerRNA tool_properties = {0};
bToolRef *keymap_tool = ((handler_base->type == WM_HANDLER_TYPE_KEYMAP) ?
((wmEventHandler_Keymap *)handler_base)->keymap_tool :
@@ -2339,46 +2339,36 @@ static int wm_handler_fileselect_do(bContext *C,
switch (val) {
case EVT_FILESELECT_FULL_OPEN: {
- ScrArea *sa;
+ wmWindow *win = CTX_wm_window(C);
+ const int sizex = 1020 * UI_DPI_FAC;
+ const int sizey = 600 * UI_DPI_FAC;
+
+ if (WM_window_open_temp(C,
+ WM_window_pixels_x(win) / 2,
+ WM_window_pixels_y(win) / 2,
+ sizex,
+ sizey,
+ WM_WINDOW_FILESEL) != NULL) {
+ ScrArea *area = CTX_wm_area(C);
+ ARegion *region_header = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
- /* sa can be null when window A is active, but mouse is over window B
- * in this case, open file select in original window A. Also don't
- * use global areas. */
- if (handler->context.area == NULL || ED_area_is_global(handler->context.area)) {
- bScreen *screen = CTX_wm_screen(C);
- sa = (ScrArea *)screen->areabase.first;
- }
- else {
- sa = handler->context.area;
- }
+ BLI_assert(area->spacetype == SPACE_FILE);
- if (sa->full) {
- /* ensure the first area becomes the file browser, because the second one is the small
- * top (info-)area which might be too small (in fullscreens we have max two areas) */
- if (sa->prev) {
- sa = sa->prev;
- }
- ED_area_newspace(C, sa, SPACE_FILE, true); /* 'sa' is modified in-place */
- /* we already had a fullscreen here -> mark new space as a stacked fullscreen */
- sa->flag |= (AREA_FLAG_STACKED_FULLSCREEN | AREA_FLAG_TEMP_TYPE);
- }
- else if (sa->spacetype == SPACE_FILE) {
- sa = ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED);
+ region_header->flag |= RGN_FLAG_HIDDEN;
+ /* Header on bottom, AZone triangle to toggle header looks misplaced at the top */
+ region_header->alignment = RGN_ALIGN_BOTTOM;
+
+ /* settings for filebrowser, sfile is not operator owner but sends events */
+ sfile = (SpaceFile *)area->spacedata.first;
+ sfile->op = handler->op;
+
+ ED_fileselect_set_params(sfile);
}
else {
- sa = ED_screen_full_newspace(C, sa, SPACE_FILE); /* sets context */
+ BKE_report(&wm->reports, RPT_ERROR, "Failed to open window!");
+ return OPERATOR_CANCELLED;
}
- /* note, getting the 'sa' back from the context causes a nasty bug where the newly created
- * 'sa' != CTX_wm_area(C). removed the line below and set 'sa' in the 'if' above */
- /* sa = CTX_wm_area(C); */
-
- /* settings for filebrowser, sfile is not operator owner but sends events */
- sfile = (SpaceFile *)sa->spacedata.first;
- sfile->op = handler->op;
-
- ED_fileselect_set_params(sfile);
-
action = WM_HANDLER_BREAK;
break;
}
@@ -2390,14 +2380,27 @@ static int wm_handler_fileselect_do(bContext *C,
BLI_remlink(handlers, handler);
if (val != EVT_FILESELECT_EXTERNAL_CANCEL) {
- ScrArea *sa = CTX_wm_area(C);
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (WM_window_is_temp_screen(win)) {
+ bScreen *screen = WM_window_get_active_screen(win);
+ ScrArea *file_sa = screen->areabase.first;
- if (sa->full) {
- ED_screen_full_prevspace(C, sa);
- }
- /* user may have left fullscreen */
- else {
- ED_area_prevspace(C, sa);
+ BLI_assert(file_sa->spacetype == SPACE_FILE);
+
+ if (BLI_listbase_is_single(&file_sa->spacedata)) {
+ wmWindow *ctx_win = CTX_wm_window(C);
+ wm_window_close(C, wm, win);
+ CTX_wm_window_set(C, ctx_win); // wm_window_close() NULLs.
+ }
+ else if (file_sa->full) {
+ ED_screen_full_prevspace(C, file_sa);
+ }
+ else {
+ ED_area_prevspace(C, file_sa);
+ }
+
+ break;
+ }
}
}
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 189c4f18613..af841f20620 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -77,6 +77,7 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
+#include "BKE_library_override.h"
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
@@ -100,6 +101,7 @@
#include "ED_datafiles.h"
#include "ED_fileselect.h"
#include "ED_image.h"
+#include "ED_outliner.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h"
@@ -1203,6 +1205,8 @@ static ImBuf *blend_file_thumb(const bContext *C,
/* will be scaled down, but gives some nice oversampling */
ImBuf *ibuf;
BlendThumbnail *thumb;
+ wmWindowManager *wm = CTX_wm_manager(C);
+ wmWindow *windrawable_old = wm->windrawable;
char err_out[256] = "unknown";
/* screen if no camera found */
@@ -1236,6 +1240,9 @@ static ImBuf *blend_file_thumb(const bContext *C,
/* gets scaled to BLEN_THUMB_SIZE */
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
+ /* Offscreen drawing requires a drawable window context. */
+ wm_window_make_drawable(wm, CTX_wm_window(C));
+
if (scene->camera) {
ibuf = ED_view3d_draw_offscreen_imbuf_simple(depsgraph,
scene,
@@ -1268,6 +1275,14 @@ static ImBuf *blend_file_thumb(const bContext *C,
err_out);
}
+ /* Reset to old drawable. */
+ if (windrawable_old) {
+ wm_window_make_drawable(wm, windrawable_old);
+ }
+ else {
+ wm_window_clear_drawable(wm);
+ }
+
if (ibuf) {
float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp);
@@ -1351,10 +1366,13 @@ static bool wm_file_write(bContext *C, const char *filepath, int fileflags, Repo
}
}
- /* Call pre-save callbacks befores writing preview,
+ /* Call pre-save callbacks before writing preview,
* that way you can generate custom file thumbnail. */
BLI_callback_exec(bmain, NULL, BLI_CB_EVT_SAVE_PRE);
+ /* Enforce full override check/generation on file save. */
+ BKE_main_override_library_operations_create(bmain, true);
+
/* blend file thumbnail */
/* Save before exit_editmode, otherwise derivedmeshes for shared data corrupt T27765. */
/* Main now can store a '.blend' thumbnail, useful for background mode
@@ -1967,6 +1985,10 @@ static int wm_homefile_read_exec(bContext *C, wmOperator *op)
}
}
+ if (G.fileflags & G_FILE_NO_UI) {
+ ED_outliner_select_sync_from_all_tag(C);
+ }
+
return OPERATOR_FINISHED;
}
@@ -2222,6 +2244,9 @@ static int wm_open_mainfile__open(bContext *C, wmOperator *op)
BKE_report_print_level_set(op->reports, RPT_WARNING);
if (success) {
+ if (G.fileflags & G_FILE_NO_UI) {
+ ED_outliner_select_sync_from_all_tag(C);
+ }
return OPERATOR_FINISHED;
}
else {
@@ -2310,7 +2335,7 @@ static void wm_open_mainfile_ui(bContext *UNUSED(C), wmOperator *op)
void WM_OT_open_mainfile(wmOperatorType *ot)
{
- ot->name = "Open Blender File";
+ ot->name = "Open";
ot->idname = "WM_OT_open_mainfile";
ot->description = "Open a Blender file";
@@ -2492,7 +2517,7 @@ void WM_OT_recover_auto_save(wmOperatorType *ot)
FILE_BLENDER,
FILE_OPENFILE,
WM_FILESEL_FILEPATH,
- FILE_LONGDISPLAY,
+ FILE_HORIZONTALDISPLAY,
FILE_SORT_TIME);
}
@@ -2626,7 +2651,7 @@ void WM_OT_save_as_mainfile(wmOperatorType *ot)
{
PropertyRNA *prop;
- ot->name = "Save As Blender File";
+ ot->name = "Save As";
ot->idname = "WM_OT_save_as_mainfile";
ot->description = "Save the current file in the desired location";
@@ -2832,6 +2857,12 @@ static uiBlock *block_create_autorun_warning(struct bContext *C,
/* Buttons */
uiBut *but;
uiLayout *split = uiLayoutSplit(layout, 0.0f, true);
+ uiLayoutSetScaleY(split, 1.2f);
+
+ /* empty space */
+ col = uiLayoutColumn(split, false);
+ uiItemS(col);
+
col = uiLayoutColumn(split, false);
/* Allow reload if we have a saved file.
@@ -2872,12 +2903,9 @@ static uiBlock *block_create_autorun_warning(struct bContext *C,
TIP_("Enable scripts"));
UI_but_func_set(but, wm_block_autorun_warning_enable_scripts, block, NULL);
}
+ UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
- /* empty space between buttons */
col = uiLayoutColumn(split, false);
- uiItemS(col);
-
- col = uiLayoutColumn(split, 1);
but = uiDefIconTextBut(block,
UI_BTYPE_BUT,
0,
@@ -2894,8 +2922,10 @@ static uiBlock *block_create_autorun_warning(struct bContext *C,
0,
TIP_("Continue using file without Python scripts"));
UI_but_func_set(but, wm_block_autorun_warning_ignore, block, NULL);
+ UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
+ UI_but_flag_enable(but, UI_BUT_ACTIVE_DEFAULT);
- UI_block_bounds_set_centered(block, 10);
+ UI_block_bounds_set_centered(block, 14 * U.dpi_fac);
return block;
}
@@ -2998,7 +3028,7 @@ static void wm_block_file_close_cancel_button(uiBlock *block, wmGenericCallback
static void wm_block_file_close_discard_button(uiBlock *block, wmGenericCallback *post_action)
{
uiBut *but = uiDefIconTextBut(
- block, UI_BTYPE_BUT, 0, 0, IFACE_("Discard Changes"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, "");
+ block, UI_BTYPE_BUT, 0, 0, IFACE_("Don't Save"), 0, 0, 0, UI_UNIT_Y, 0, 0, 0, 0, 0, "");
UI_but_func_set(but, wm_block_file_close_discard, block, post_action);
UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT);
}
@@ -3018,8 +3048,28 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi
{
wmGenericCallback *post_action = (wmGenericCallback *)arg1;
Main *bmain = CTX_data_main(C);
-
uiStyle *style = UI_style_get();
+ uiFontStyle *fs = &style->widgetlabel;
+
+ /* Filename */
+ const char *blendfile_pathpath = BKE_main_blendfile_path(bmain);
+ char filename[FILE_MAX];
+ if (blendfile_pathpath[0] != '\0') {
+ BLI_split_file_part(blendfile_pathpath, filename, sizeof(filename));
+ BLI_path_extension_replace(filename, sizeof(filename), "");
+ }
+ else {
+ STRNCPY(filename, IFACE_("Untitled"));
+ }
+
+ /* Title */
+ char title[FILE_MAX + 100];
+ UI_text_clip_middle_ex(
+ fs, filename, U.widget_unit * 9, U.widget_unit * 2, sizeof(filename), '\0');
+ BLI_snprintf(title, sizeof(title), TIP_("Save changes to \"%s\" before closing?"), filename);
+ int title_width = MAX2(UI_fontstyle_string_width(fs, title), U.widget_unit * 22);
+
+ /* Create dialog */
uiBlock *block = UI_block_begin(C, ar, close_file_dialog_name, UI_EMBOSS);
UI_block_flag_enable(
@@ -3032,25 +3082,25 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi
UI_LAYOUT_PANEL,
10,
2,
- U.widget_unit * 24,
+ U.widget_unit * 2 + title_width,
U.widget_unit * 6,
0,
style);
/* Title */
- bool blend_file_is_saved = BKE_main_blendfile_path(bmain)[0] != '\0';
- if (blend_file_is_saved) {
- uiItemL(layout, "This file has unsaved changes.", ICON_INFO);
- }
- else {
- uiItemL(layout, "This file has not been saved yet.", ICON_INFO);
- }
+ uiItemL(layout, title, ICON_ERROR);
/* Image Saving */
ReportList reports;
BKE_reports_init(&reports, RPT_STORE);
uint modified_images_count = ED_image_save_all_modified_info(C, &reports);
+ LISTBASE_FOREACH (Report *, report, &reports.list) {
+ uiLayout *row = uiLayoutRow(layout, false);
+ uiLayoutSetRedAlert(row, true);
+ uiItemL(row, report->message, ICON_CANCEL);
+ }
+
if (modified_images_count > 0) {
char message[64];
BLI_snprintf(message,
@@ -3058,6 +3108,7 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi
(modified_images_count == 1) ? "Save %u modified image" :
"Save %u modified images",
modified_images_count);
+ uiItemS(layout);
uiDefButBitC(block,
UI_BTYPE_CHECKBOX,
1,
@@ -3075,13 +3126,9 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi
"");
}
- LISTBASE_FOREACH (Report *, report, &reports.list) {
- uiItemL(layout, report->message, ICON_ERROR);
- }
-
BKE_reports_clear(&reports);
- uiItemL(layout, "", ICON_NONE);
+ uiItemS_ex(layout, 3.0f);
/* Buttons */
#ifdef _WIN32
@@ -3090,10 +3137,12 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi
const bool windows_layout = false;
#endif
- uiLayout *split = uiLayoutSplit(layout, 0.0f, true);
-
if (windows_layout) {
/* Windows standard layout. */
+
+ uiLayout *split = uiLayoutSplit(layout, 0.18f, true);
+ uiLayoutSetScaleY(split, 1.2f);
+
uiLayout *col = uiLayoutColumn(split, false);
uiItemS(col);
@@ -3108,20 +3157,24 @@ static uiBlock *block_create__close_file_dialog(struct bContext *C, struct ARegi
}
else {
/* macOS and Linux standard layout. */
- uiLayout *col = uiLayoutColumn(split, false);
+
+ uiLayout *split = uiLayoutSplit(layout, 0.0f, true);
+ uiLayoutSetScaleY(split, 1.2f);
+
+ uiLayout *col = uiLayoutColumn(split, true);
wm_block_file_close_discard_button(block, post_action);
- col = uiLayoutColumn(split, false);
+ col = uiLayoutColumn(split, true);
uiItemS(col);
- col = uiLayoutColumn(split, false);
+ col = uiLayoutColumn(split, true);
wm_block_file_close_cancel_button(block, post_action);
col = uiLayoutColumn(split, false);
wm_block_file_close_save_button(block, post_action);
}
- UI_block_bounds_set_centered(block, 10);
+ UI_block_bounds_set_centered(block, 14 * U.dpi_fac);
return block;
}
diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index 5a6606984ba..2cd2cf0636a 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -561,7 +561,7 @@ static void wm_link_append_properties_common(wmOperatorType *ot, bool is_link)
void WM_OT_link(wmOperatorType *ot)
{
- ot->name = "Link from Library";
+ ot->name = "Link";
ot->idname = "WM_OT_link";
ot->description = "Link from a Library .blend file";
@@ -585,7 +585,7 @@ void WM_OT_link(wmOperatorType *ot)
void WM_OT_append(wmOperatorType *ot)
{
- ot->name = "Append from Library";
+ ot->name = "Append";
ot->idname = "WM_OT_append";
ot->description = "Append from a Library .blend file";
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 29cb02888ac..d08f4e236ee 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -524,6 +524,7 @@ void WM_exit_ex(bContext *C, const bool do_python)
BKE_addon_pref_type_free();
BKE_keyconfig_pref_type_free();
+ BKE_material_gpencil_default_free();
wm_operatortype_free();
wm_dropbox_free();
diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c
index fcb55d3f801..663e4adf06b 100644
--- a/source/blender/windowmanager/intern/wm_operator_props.c
+++ b/source/blender/windowmanager/intern/wm_operator_props.c
@@ -65,19 +65,27 @@ void WM_operator_properties_filesel(wmOperatorType *ot,
0,
"Default",
"Automatically determine display type for files"},
- {FILE_SHORTDISPLAY,
- "LIST_SHORT",
- ICON_SHORTDISPLAY,
+ {FILE_VERTICALDISPLAY,
+ "LIST_VERTICAL",
+ ICON_SHORTDISPLAY, /* Name of deprecated short list */
"Short List",
"Display files as short list"},
- {FILE_LONGDISPLAY,
- "LIST_LONG",
- ICON_LONGDISPLAY,
+ {FILE_HORIZONTALDISPLAY,
+ "LIST_HORIZONTAL",
+ ICON_LONGDISPLAY, /* Name of deprecated long list */
"Long List",
"Display files as a detailed list"},
{FILE_IMGDISPLAY, "THUMBNAIL", ICON_IMGDISPLAY, "Thumbnails", "Display files as thumbnails"},
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem file_action_types[] = {
+ {FILE_OPENFILE,
+ "OPENFILE",
+ 0,
+ "Open",
+ "Use the file browser for opening files or a directory"},
+ {FILE_SAVE, "SAVE", 0, "Save", "Use the file browser for saving a file"},
+ };
if (flag & WM_FILESEL_FILEPATH) {
RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Path to file");
@@ -99,6 +107,15 @@ void WM_operator_properties_filesel(wmOperatorType *ot,
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
+ if ((flag & WM_FILESEL_SHOW_PROPS) == 0) {
+ prop = RNA_def_boolean(ot->srna,
+ "hide_props_region",
+ true,
+ "Hide Operator Properties",
+ "Collapse the region displaying the operator settings");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+ }
+
if (action == FILE_SAVE) {
/* note, this is only used to check if we should highlight the filename area red when the
* filepath is an existing file. */
@@ -186,6 +203,9 @@ void WM_operator_properties_filesel(wmOperatorType *ot,
prop = RNA_def_enum(
ot->srna, "sort_method", rna_enum_file_sort_items, sort, "File sorting mode", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
+
+ prop = RNA_def_enum(ot->srna, "action_type", file_action_types, action, "Action Type", "");
+ RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
static void wm_operator_properties_select_action_ex(wmOperatorType *ot,
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 29ecf798b3c..9657347a1c4 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -368,7 +368,7 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr
continue;
}
- if (ptr->id.data == ctx_item_ptr.id.data) {
+ if (ptr->owner_id == ctx_item_ptr.owner_id) {
if ((ptr->data == ctx_item_ptr.data) && (ptr->type == ctx_item_ptr.type)) {
/* found! */
member_found = identifier;
@@ -402,13 +402,13 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr
{
const char *member_id = NULL;
- if (ptr->id.data) {
+ if (ptr->owner_id) {
# define CTX_TEST_PTR_ID(C, member, idptr) \
{ \
const char *ctx_member = member; \
PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \
- if (ctx_item_ptr.id.data == idptr) { \
+ if (ctx_item_ptr.owner_id == idptr) { \
member_id = ctx_member; \
break; \
} \
@@ -420,7 +420,7 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr
const char *ctx_member = member; \
const char *ctx_member_full = member_full; \
PointerRNA ctx_item_ptr = CTX_data_pointer_get(C, ctx_member); \
- if (ctx_item_ptr.id.data && cast(ctx_item_ptr.id.data) == idptr) { \
+ if (ctx_item_ptr.owner_id && (ID *)cast(ctx_item_ptr.owner_id) == idptr) { \
member_id = ctx_member_full; \
break; \
} \
@@ -447,19 +447,19 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr
} \
(void)0
- switch (GS(((ID *)ptr->id.data)->name)) {
+ switch (GS(ptr->owner_id->name)) {
case ID_SCE: {
- CTX_TEST_PTR_ID(C, "scene", ptr->id.data);
+ CTX_TEST_PTR_ID(C, "scene", ptr->owner_id);
break;
}
case ID_OB: {
- CTX_TEST_PTR_ID(C, "object", ptr->id.data);
+ CTX_TEST_PTR_ID(C, "object", ptr->owner_id);
break;
}
/* from rna_Main_objects_new */
case OB_DATA_SUPPORT_ID_CASE: {
# define ID_CAST_OBDATA(id_pt) (((Object *)(id_pt))->data)
- CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->id.data);
+ CTX_TEST_PTR_ID_CAST(C, "object", "object.data", ID_CAST_OBDATA, ptr->owner_id);
break;
# undef ID_CAST_OBDATA
}
@@ -467,18 +467,18 @@ static const char *wm_context_member_from_ptr(bContext *C, const PointerRNA *ptr
# define ID_CAST_OBMATACT(id_pt) \
(give_current_material(((Object *)id_pt), ((Object *)id_pt)->actcol))
CTX_TEST_PTR_ID_CAST(
- C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->id.data);
+ C, "object", "object.active_material", ID_CAST_OBMATACT, ptr->owner_id);
break;
# undef ID_CAST_OBMATACT
}
case ID_WO: {
# define ID_CAST_SCENEWORLD(id_pt) (((Scene *)(id_pt))->world)
- CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->id.data);
+ CTX_TEST_PTR_ID_CAST(C, "scene", "scene.world", ID_CAST_SCENEWORLD, ptr->owner_id);
break;
# undef ID_CAST_SCENEWORLD
}
case ID_SCR: {
- CTX_TEST_PTR_ID(C, "screen", ptr->id.data);
+ CTX_TEST_PTR_ID(C, "screen", ptr->owner_id);
SpaceLink *space_data = CTX_wm_space_data(C);
@@ -539,7 +539,7 @@ char *WM_prop_pystring_assign(bContext *C, PointerRNA *ptr, PropertyRNA *prop, i
if (lhs == NULL) {
/* fallback to bpy.data.foo[id] if we dont find in the context */
- lhs = RNA_path_full_property_py(ptr, prop, index);
+ lhs = RNA_path_full_property_py(CTX_data_main(C), ptr, prop, index);
}
if (!lhs) {
@@ -850,7 +850,7 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg)
NULL);
/* Move it downwards, mouse over button. */
- UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y});
+ UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, (const int[2]){0, -UI_UNIT_Y});
UI_but_focus_on_enter_event(win, but);
@@ -1111,7 +1111,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op)
/* if register is not enabled, the operator gets freed on OPERATOR_FINISHED
* ui_apply_but_funcs_after calls ED_undo_operator_repeate_cb and crashes */
- assert(op->type->flag & OPTYPE_REGISTER);
+ BLI_assert(op->type->flag & OPTYPE_REGISTER);
UI_block_func_handle_set(block, wm_block_redo_cb, arg_op);
layout = UI_block_layout(
@@ -1126,18 +1126,15 @@ 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, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
- if (op->next) {
- uiItemS(layout);
- }
+ C, layout, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
}
}
else {
uiTemplateOperatorPropertyButs(
- C, layout, op, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
+ C, layout, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
}
- UI_block_bounds_set_popup(block, 4, NULL);
+ UI_block_bounds_set_popup(block, 6 * U.dpi_fac, NULL);
return block;
}
@@ -1217,7 +1214,8 @@ static uiBlock *wm_block_dialog_create(bContext *C, ARegion *ar, void *userData)
}
/* center around the mouse */
- UI_block_bounds_set_popup(block, 4, (const int[2]){data->width / -2, data->height / 2});
+ UI_block_bounds_set_popup(
+ block, 6 * U.dpi_fac, (const int[2]){data->width / -2, data->height / 2});
UI_block_active_only_flagged_buttons(C, ar, block);
@@ -1245,7 +1243,7 @@ static uiBlock *wm_operator_ui_create(bContext *C, ARegion *ar, void *userData)
UI_block_func_set(block, NULL, NULL, NULL);
- UI_block_bounds_set_popup(block, 4, NULL);
+ UI_block_bounds_set_popup(block, 6 * U.dpi_fac, NULL);
UI_block_active_only_flagged_buttons(C, ar, block);
@@ -1516,7 +1514,7 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *userdata)
NULL);
/* Move it downwards, mouse over button. */
- UI_block_bounds_set_popup(block, 6, (const int[2]){0, -UI_UNIT_Y});
+ UI_block_bounds_set_popup(block, 0.3f * U.widget_unit, (const int[2]){0, -UI_UNIT_Y});
return block;
}
@@ -3011,7 +3009,7 @@ static void WM_OT_redraw_timer(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Reporet Memory Statistics
+/** \name Report Memory Statistics
*
* Use for testing/debugging.
* \{ */
diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c
index 8629997030f..d3f7661a008 100644
--- a/source/blender/windowmanager/intern/wm_splash_screen.c
+++ b/source/blender/windowmanager/intern/wm_splash_screen.c
@@ -113,31 +113,37 @@ static void wm_block_splash_add_label(uiBlock *block, const char *label, int x,
static void wm_block_splash_add_labels(uiBlock *block, int x, int y)
{
/* Version number. */
- const char *version_suffix = NULL;
+ const char *version_cycle = NULL;
bool show_build_info = true;
if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) {
- version_suffix = " Alpha";
+ version_cycle = " Alpha";
}
else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "beta")) {
- version_suffix = " Beta";
+ version_cycle = " Beta";
}
else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "rc")) {
- version_suffix = " Release Candidate";
+ version_cycle = " Release Candidate";
show_build_info = false;
}
else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
- version_suffix = STRINGIFY(BLENDER_VERSION_CHAR);
+ version_cycle = STRINGIFY(BLENDER_VERSION_CHAR);
show_build_info = false;
}
+ const char *version_cycle_number = "";
+ if (strlen(STRINGIFY(BLENDER_VERSION_CYCLE_NUMBER))) {
+ version_cycle_number = " " STRINGIFY(BLENDER_VERSION_CYCLE_NUMBER);
+ }
+
char version_buf[256] = "\0";
BLI_snprintf(version_buf,
sizeof(version_buf),
- "v %d.%d%s",
+ "v %d.%d%s%s",
BLENDER_VERSION / 100,
BLENDER_VERSION % 100,
- version_suffix);
+ version_cycle,
+ version_cycle_number);
wm_block_splash_add_label(block, version_buf, x, &y);
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index d17b8817691..91173804b18 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -482,8 +482,8 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
}
/* Informs GHOST of unsaved changes, to set window modified visual indicator (macOS)
- * and to give hint of unsaved changes for a user warning mechanism in case of OS
- * application terminate request (e.g. OS Shortcut Alt+F4, Cmd+Q, (...), or session end). */
+ * and to give hint of unsaved changes for a user warning mechanism in case of OS application
+ * terminate request (e.g. OS Shortcut Alt+F4, Command+Q, (...), or session end). */
GHOST_SetWindowModifiedState(win->ghostwin, (GHOST_TUns8)!wm->file_saved);
}
}
@@ -658,7 +658,7 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm)
BLI_assert(G.background == false);
- /* no commandline prefsize? then we set this.
+ /* No command-line prefsize? then we set this.
* Note that these values will be used only
* when there is no startup.blend yet.
*/
@@ -807,6 +807,7 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
ScrArea *sa;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
+ eSpace_Type space_type = SPACE_EMPTY;
const char *title;
/* convert to native OS window coordinates */
@@ -888,14 +889,24 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
CTX_wm_area_set(C, sa);
if (type == WM_WINDOW_RENDER) {
- ED_area_newspace(C, sa, SPACE_IMAGE, false);
+ space_type = SPACE_IMAGE;
}
else if (type == WM_WINDOW_DRIVERS) {
- ED_area_newspace(C, sa, SPACE_GRAPH, false);
+ space_type = SPACE_GRAPH;
+ }
+ else if (type == WM_WINDOW_USERPREFS) {
+ space_type = SPACE_USERPREF;
+ }
+ else if (type == WM_WINDOW_FILESEL) {
+ space_type = SPACE_FILE;
+ }
+ else if (type == WM_WINDOW_INFO) {
+ space_type = SPACE_INFO;
}
else {
- ED_area_newspace(C, sa, SPACE_USERPREF, false);
+ BLI_assert(false);
}
+ ED_area_newspace(C, sa, space_type, false);
ED_screen_change(C, screen);
ED_screen_refresh(CTX_wm_manager(C), win); /* test scale */
@@ -917,6 +928,9 @@ wmWindow *WM_window_open_temp(bContext *C, int x, int y, int sizex, int sizey, i
else if (sa->spacetype == SPACE_GRAPH) {
title = IFACE_("Blender Drivers Editor");
}
+ else if (sa->spacetype == SPACE_INFO) {
+ title = IFACE_("Blender Info Log");
+ }
else {
title = "Blender";
}
diff --git a/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c b/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c
index 73758e2d98f..0c2ce9783ec 100644
--- a/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c
+++ b/source/blender/windowmanager/message_bus/intern/wm_message_bus_rna.c
@@ -50,7 +50,7 @@ static uint wm_msg_rna_gset_hash(const void *key_p)
// printf("%s\n", RNA_struct_identifier(params->ptr.type));
uint k = void_hash_uint(params->ptr.type);
k ^= void_hash_uint(params->ptr.data);
- k ^= void_hash_uint(params->ptr.id.data);
+ k ^= void_hash_uint(params->ptr.owner_id);
k ^= void_hash_uint(params->prop);
return k;
}
@@ -59,7 +59,7 @@ static bool wm_msg_rna_gset_cmp(const void *key_a_p, const void *key_b_p)
const wmMsgParams_RNA *params_a = &((const wmMsgSubscribeKey_RNA *)key_a_p)->msg.params;
const wmMsgParams_RNA *params_b = &((const wmMsgSubscribeKey_RNA *)key_b_p)->msg.params;
return !((params_a->ptr.type == params_b->ptr.type) &&
- (params_a->ptr.id.data == params_b->ptr.id.data) &&
+ (params_a->ptr.owner_id == params_b->ptr.owner_id) &&
(params_a->ptr.data == params_b->ptr.data) && (params_a->prop == params_b->prop));
}
static void wm_msg_rna_gset_key_free(void *key_p)
@@ -100,7 +100,7 @@ static void wm_msg_rna_update_by_id(struct wmMsgBus *mbus, ID *id_src, ID *id_ds
while (BLI_gsetIterator_done(&gs_iter) == false) {
wmMsgSubscribeKey_RNA *key = BLI_gsetIterator_getKey(&gs_iter);
BLI_gsetIterator_step(&gs_iter);
- if (key->msg.params.ptr.id.data == id_src) {
+ if (key->msg.params.ptr.owner_id == id_src) {
/* GSet always needs updating since the key changes. */
BLI_gset_remove(gs, key, NULL);
@@ -123,10 +123,10 @@ static void wm_msg_rna_update_by_id(struct wmMsgBus *mbus, ID *id_src, ID *id_ds
if (BLI_listbase_is_empty(&key->head.values)) {
/* Remove, no reason to keep. */
}
- else if (key->msg.params.ptr.data == key->msg.params.ptr.id.data) {
+ else if (key->msg.params.ptr.data == key->msg.params.ptr.owner_id) {
/* Simple, just update the ID. */
key->msg.params.ptr.data = id_dst;
- key->msg.params.ptr.id.data = id_dst;
+ key->msg.params.ptr.owner_id = id_dst;
remove = false;
}
else {
@@ -177,7 +177,7 @@ static void wm_msg_rna_remove_by_id(struct wmMsgBus *mbus, const ID *id)
while (BLI_gsetIterator_done(&gs_iter) == false) {
wmMsgSubscribeKey_RNA *key = BLI_gsetIterator_getKey(&gs_iter);
BLI_gsetIterator_step(&gs_iter);
- if (key->msg.params.ptr.id.data == id) {
+ if (key->msg.params.ptr.owner_id == id) {
/* Clear here so we can decrement 'messages_tag_count'. */
for (wmMsgSubscribeValueLink *msg_lnk = key->head.values.first, *msg_lnk_next; msg_lnk;
msg_lnk = msg_lnk_next) {
@@ -226,7 +226,7 @@ void WM_msg_publish_rna_params(struct wmMsgBus *mbus, const wmMsgParams_RNA *msg
CLOG_INFO(WM_LOG_MSGBUS_PUB,
2,
"rna(id='%s', %s.%s)",
- msg_key_params->ptr.id.data ? ((ID *)msg_key_params->ptr.id.data)->name : none,
+ msg_key_params->ptr.owner_id ? ((ID *)msg_key_params->ptr.owner_id)->name : none,
msg_key_params->ptr.type ? RNA_struct_identifier(msg_key_params->ptr.type) : none,
msg_key_params->prop ? RNA_property_identifier((PropertyRNA *)msg_key_params->prop) :
none);
@@ -237,7 +237,7 @@ void WM_msg_publish_rna_params(struct wmMsgBus *mbus, const wmMsgParams_RNA *msg
/* Support anonymous subscribers, this may be some extra overhead
* but we want to be able to be more ambiguous. */
- if (msg_key_params->ptr.id.data || msg_key_params->ptr.data) {
+ if (msg_key_params->ptr.owner_id || msg_key_params->ptr.data) {
wmMsgParams_RNA msg_key_params_anon = *msg_key_params;
/* We might want to enable this later? */
@@ -250,7 +250,7 @@ void WM_msg_publish_rna_params(struct wmMsgBus *mbus, const wmMsgParams_RNA *msg
msg_key_params_anon.prop = msg_key_params->prop;
}
- msg_key_params_anon.ptr.id.data = NULL;
+ msg_key_params_anon.ptr.owner_id = NULL;
msg_key_params_anon.ptr.data = NULL;
if ((key = WM_msg_lookup_rna(mbus, &msg_key_params_anon))) {
WM_msg_publish_with_key(mbus, &key->head);
@@ -292,7 +292,7 @@ void WM_msg_subscribe_rna_params(struct wmMsgBus *mbus,
CLOG_INFO(WM_LOG_MSGBUS_SUB,
3,
"rna(id='%s', %s.%s, info='%s')",
- msg_key_params->ptr.id.data ? ((ID *)msg_key_params->ptr.id.data)->name : none,
+ msg_key_params->ptr.owner_id ? ((ID *)msg_key_params->ptr.owner_id)->name : none,
msg_key_params->ptr.type ? RNA_struct_identifier(msg_key_params->ptr.type) : none,
msg_key_params->prop ? RNA_property_identifier((PropertyRNA *)msg_key_params->prop) :
none,
@@ -303,7 +303,7 @@ void WM_msg_subscribe_rna_params(struct wmMsgBus *mbus,
if (msg_val_params->is_persistent) {
if (msg_key->msg.params.data_path == NULL) {
- if (msg_key->msg.params.ptr.data != msg_key->msg.params.ptr.id.data) {
+ if (msg_key->msg.params.ptr.data != msg_key->msg.params.ptr.owner_id) {
/* We assume prop type can't change. */
msg_key->msg.params.data_path = RNA_path_from_ID_to_struct(&msg_key->msg.params.ptr);
}
@@ -339,14 +339,14 @@ void WM_msg_subscribe_ID(struct wmMsgBus *mbus,
const wmMsgSubscribeValue *msg_val_params,
const char *id_repr)
{
- wmMsgParams_RNA msg_key_params = {{{NULL}}};
+ wmMsgParams_RNA msg_key_params = {NULL};
RNA_id_pointer_create(id, &msg_key_params.ptr);
WM_msg_subscribe_rna_params(mbus, &msg_key_params, msg_val_params, id_repr);
}
void WM_msg_publish_ID(struct wmMsgBus *mbus, ID *id)
{
- wmMsgParams_RNA msg_key_params = {{{NULL}}};
+ wmMsgParams_RNA msg_key_params = {NULL};
RNA_id_pointer_create(id, &msg_key_params.ptr);
WM_msg_publish_rna_params(mbus, &msg_key_params);
}
diff --git a/source/blender/windowmanager/message_bus/wm_message_bus.h b/source/blender/windowmanager/message_bus/wm_message_bus.h
index 4a8bce52992..4ee087593ac 100644
--- a/source/blender/windowmanager/message_bus/wm_message_bus.h
+++ b/source/blender/windowmanager/message_bus/wm_message_bus.h
@@ -23,7 +23,6 @@
#include <stdio.h>
-struct GSet;
struct ID;
struct bContext;
struct wmMsg;
@@ -173,7 +172,7 @@ void WM_msg_subscribe_static(struct wmMsgBus *mbus,
/* wm_message_bus_rna.c */
typedef struct wmMsgParams_RNA {
- /** when #PointerRNA.data & id.data are NULL. match against all. */
+ /** when #PointerRNA.data & owner_id are NULL. match against all. */
PointerRNA ptr;
/** when NULL, match against any property. */
const PropertyRNA *prop;
@@ -233,7 +232,7 @@ void WM_msg_publish_ID(struct wmMsgBus *mbus, struct ID *id);
#define WM_msg_publish_rna_prop(mbus, id_, data_, type_, prop_) \
{ \
- wmMsgParams_RNA msg_key_params_ = {{{0}}}; \
+ wmMsgParams_RNA msg_key_params_ = {{0}}; \
_WM_MESSAGE_EXTERN_BEGIN; \
extern PropertyRNA rna_##type_##_##prop_; \
_WM_MESSAGE_EXTERN_END; \
@@ -244,7 +243,7 @@ void WM_msg_publish_ID(struct wmMsgBus *mbus, struct ID *id);
((void)0)
#define WM_msg_subscribe_rna_prop(mbus, id_, data_, type_, prop_, value) \
{ \
- wmMsgParams_RNA msg_key_params_ = {{{0}}}; \
+ wmMsgParams_RNA msg_key_params_ = {{0}}; \
_WM_MESSAGE_EXTERN_BEGIN; \
extern PropertyRNA rna_##type_##_##prop_; \
_WM_MESSAGE_EXTERN_END; \
diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h
index 90c580818c9..b0329f7415e 100644
--- a/source/blender/windowmanager/wm_window.h
+++ b/source/blender/windowmanager/wm_window.h
@@ -24,10 +24,6 @@
#ifndef __WM_WINDOW_H__
#define __WM_WINDOW_H__
-struct EnumPropertyItem;
-struct PointerRNA;
-struct PropertyRNA;
-struct wmEvent;
struct wmOperator;
/* *************** internal api ************** */